diff --git a/src/policy/policy.h b/src/policy/policy.h
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -127,4 +127,14 @@
 extern CFeeRate dustRelayFee;
 extern uint32_t nBytesPerSigOp;
 
+/** Compute the virtual transaction size (weight reinterpreted as bytes). */
+int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigOpCost,
+                                  unsigned int bytes_per_sigop);
+int64_t GetVirtualTransactionSize(const CTransaction &tx, int64_t nSigOpCost,
+                                  unsigned int bytes_per_sigop);
+
+static inline int64_t GetVirtualTransactionSize(const CTransaction &tx) {
+    return GetVirtualTransactionSize(tx, 0, 0);
+}
+
 #endif // BITCOIN_POLICY_POLICY_H
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -177,3 +177,14 @@
 
 CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
 uint32_t nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
+
+int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigOpCost,
+                                  unsigned int bytes_per_sigop) {
+    return nSize;
+}
+
+int64_t GetVirtualTransactionSize(const CTransaction &tx, int64_t nSigOpCost,
+                                  unsigned int bytes_per_sigop) {
+    return GetVirtualTransactionSize(::GetSerializeSize(tx, PROTOCOL_VERSION),
+                                     nSigOpCost, bytes_per_sigop);
+}
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -137,7 +137,7 @@
     tx.vout[0].nValue = int64_t(5000000000LL - 1000 - 50000) * SATOSHI;
     TxId freeTxId = tx.GetId();
     g_mempool.addUnchecked(freeTxId, entry.Fee(Amount::zero()).FromTx(tx));
-    size_t freeTxSize = CTransaction(tx).GetBillableSize();
+    size_t freeTxSize = GetVirtualTransactionSize(CTransaction(tx));
 
     // Calculate a fee on child transaction that will put the package just
     // below the block min tx fee (assuming 1 child tx of the same size).