Transaction: Add methods for calculating transaction weight and virtual transaction size.

This commit is contained in:
Andreas Schildbach 2019-04-20 17:31:36 +02:00
parent 6d7866d476
commit c97ecf6046
2 changed files with 40 additions and 2 deletions

View file

@ -307,6 +307,29 @@ public class Transaction extends ChildMessage {
return cachedWTxId; return cachedWTxId;
} }
/** Gets the transaction weight as defined in BIP141. */
public int getWeight() {
if (!hasWitnesses())
return getMessageSize() * 4;
try (final ByteArrayOutputStream stream = new UnsafeByteArrayOutputStream(length)) {
bitcoinSerializeToStream(stream, false);
final int baseSize = stream.size();
stream.reset();
bitcoinSerializeToStream(stream, true);
final int totalSize = stream.size();
return baseSize * 3 + totalSize;
} catch (IOException e) {
throw new RuntimeException(e); // cannot happen
}
}
/** Gets the virtual transaction size as defined in BIP141. */
public int getVsize() {
if (!hasWitnesses())
return getMessageSize();
return (getWeight() + 3) / 4; // round up
}
/** /**
* Gets the sum of the inputs, regardless of who owns them. * Gets the sum of the inputs, regardless of who owns them.
*/ */
@ -863,8 +886,13 @@ public class Transaction extends ChildMessage {
final Coin fee = getFee(); final Coin fee = getFee();
if (fee != null) { if (fee != null) {
final int size = unsafeBitcoinSerialize().length; final int size = unsafeBitcoinSerialize().length;
s.append(indent).append(" fee ").append(fee.multiply(1000).divide(size).toFriendlyString()).append("/kB, ") final int vsize = getVsize();
.append(fee.toFriendlyString()).append(" for ").append(size).append(" bytes\n"); s.append(indent).append(" fee ").append(fee.multiply(1000).divide(size).toFriendlyString())
.append("/kB ");
s.append(fee.toFriendlyString()).append(" for ");
if (size != vsize)
s.append(vsize).append(" virtual bytes, ");
s.append(size).append(" bytes\n");
} }
return s.toString(); return s.toString();
} }

View file

@ -735,4 +735,14 @@ public class TransactionTest {
uint32ToByteStreamLE(getLockTime(), stream); uint32ToByteStreamLE(getLockTime(), stream);
} }
} }
@Test
public void getWeightAndVsize() {
// example from https://en.bitcoin.it/wiki/Weight_units
String txHex = "0100000000010115e180dc28a2327e687facc33f10f2a20da717e5548406f7ae8b4c811072f85603000000171600141d7cd6c75c2e86f4cbf98eaed221b30bd9a0b928ffffffff019caef505000000001976a9141d7cd6c75c2e86f4cbf98eaed221b30bd9a0b92888ac02483045022100f764287d3e99b1474da9bec7f7ed236d6c81e793b20c4b5aa1f3051b9a7daa63022016a198031d5554dbb855bdbe8534776a4be6958bd8d530dc001c32b828f6f0ab0121038262a6c6cec93c2d3ecd6c6072efea86d02ff8e3328bbd0242b20af3425990ac00000000";
Transaction tx = new Transaction(UNITTEST, HEX.decode(txHex));
assertEquals(218, tx.getMessageSize());
assertEquals(542, tx.getWeight());
assertEquals(136, tx.getVsize());
}
} }