Skip to content

Commit

Permalink
Merge bitcoin#16525: Dump transaction version as an unsigned integer …
Browse files Browse the repository at this point in the history
…in RPC/TxToUniv

e80259f Additionally treat Tx.nVersion as unsigned in joinpsbts (Matt Corallo)
970de70 Dump transaction version as an unsigned integer in RPC/TxToUniv (Matt Corallo)

Pull request description:

  Consensus-wise we already treat it as an unsigned integer (the
  only rules around it are in CSV/locktime handling), but changing
  the underlying data type means touching consensus code for a
  simple cleanup change, which isn't really worth it.

  See-also, rust-bitcoin/rust-bitcoin#299

ACKs for top commit:
  sipa:
    ACK e80259f
  practicalswift:
    ACK e80259f
  ajtowns:
    ACK e80259f code review -- checked all other uses of tx.nVersion treat it as unsigned (except for policy.cpp:IsStandard anyway), so looks good.
  naumenkogs:
    ACK e80259f

Tree-SHA512: 6760a2c77e24e9e1f79a336ca925f9bbca3a827ce02003c71d7f214b82ed3dea13fa7d9f87df9b9445cd58dff8b44a15571d821c876f22f8e5a372a014c9976b
  • Loading branch information
laanwj authored and vijaydasmp committed Nov 28, 2023
1 parent b958d40 commit 26c0c24
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 6 deletions.
9 changes: 9 additions & 0 deletions doc/release-notes-16525.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
RPC changes
-----------

Exposed transaction version numbers are now treated as unsigned 32-bit integers
instead of signed 32-bit integers. This matches their treatment in consensus
logic. Versions greater than 2 continue to be non-standard (matching previous
behavior of smaller than 1 or greater than 2 being non-standard). Note that
this includes the joinpsbt command, which combines partially-signed
transactions by selecting the highest version number.
4 changes: 3 additions & 1 deletion src/core_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
{
uint256 txid = tx.GetHash();
entry.pushKV("txid", txid.GetHex());
entry.pushKV("version", tx.nVersion);
// Transaction version is actually unsigned in consensus checks, just signed in memory,
// so cast to unsigned before giving it to the user.
entry.pushKV("version", static_cast<int64_t>(static_cast<uint32_t>(tx.nVersion)));
entry.pushKV("type", tx.nType);
entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
entry.pushKV("locktime", (int64_t)tx.nLockTime);
Expand Down
8 changes: 4 additions & 4 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1604,7 +1604,7 @@ UniValue joinpsbts(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "At least two PSBTs are required to join PSBTs.");
}

int32_t best_version = 1;
uint32_t best_version = 1;
uint32_t best_locktime = 0xffffffff;
for (unsigned int i = 0; i < txs.size(); ++i) {
PartiallySignedTransaction psbtx;
Expand All @@ -1614,8 +1614,8 @@ UniValue joinpsbts(const JSONRPCRequest& request)
}
psbtxs.push_back(psbtx);
// Choose the highest version number
if (psbtx.tx->nVersion > best_version) {
best_version = psbtx.tx->nVersion;
if (static_cast<uint32_t>(psbtx.tx->nVersion) > best_version) {
best_version = static_cast<uint32_t>(psbtx.tx->nVersion);
}
// Choose the lowest lock time
if (psbtx.tx->nLockTime < best_locktime) {
Expand All @@ -1626,7 +1626,7 @@ UniValue joinpsbts(const JSONRPCRequest& request)
// Create a blank psbt where everything will be added
PartiallySignedTransaction merged_psbt;
merged_psbt.tx = CMutableTransaction();
merged_psbt.tx->nVersion = best_version;
merged_psbt.tx->nVersion = static_cast<int32_t>(best_version);
merged_psbt.tx->nLockTime = best_locktime;

// Merge
Expand Down
3 changes: 2 additions & 1 deletion test/functional/rpc_rawtransaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,11 +359,12 @@ def run_test(self):
# Note, this is different to bitcoin. Bitcoin has a 32 bit integer
# representing the version, we have 16 bits of version and 16 bits of
# type.
# As transaction version is unsigned, this should convert to its unsigned equivalent.
tx = CTransaction()
tx.nVersion = -0x8000
rawtx = ToHex(tx)
decrawtx = self.nodes[0].decoderawtransaction(rawtx)
assert_equal(decrawtx['version'], -0x8000)
assert_equal(decrawtx['version'], 0x80000000)

# Test the maximum transaction version number that fits in a signed 32-bit integer.
tx = CTransaction()
Expand Down

0 comments on commit 26c0c24

Please sign in to comment.