From da20b02906e55a8b9727babf6cb583b029244813 Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Thu, 9 Jul 2015 15:05:36 +0200 Subject: [PATCH] Implement special priority tx size calculation. --- .../java/org/bitcoinj/core/Transaction.java | 17 ++++++++ .../org/bitcoinj/core/TransactionTest.java | 40 +++++++++++-------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/core/Transaction.java b/core/src/main/java/org/bitcoinj/core/Transaction.java index e247735d..9d7adbd2 100644 --- a/core/src/main/java/org/bitcoinj/core/Transaction.java +++ b/core/src/main/java/org/bitcoinj/core/Transaction.java @@ -583,6 +583,23 @@ public class Transaction extends ChildMessage implements Serializable { return optimalEncodingMessageSize; } + /** + * The priority (coin age) calculation doesn't use the regular message size, but rather one adjusted downwards + * for the number of inputs. The goal is to incentivise cleaning up the UTXO set with free transactions, if one + * can do so. + */ + public int getMessageSizeForPriorityCalc() { + int size = getMessageSize(); + for (TransactionInput input : inputs) { + // 41: min size of an input + // 110: enough to cover a compressed pubkey p2sh redemption (somewhat arbitrary). + int benefit = 41 + Math.min(110, input.getScriptSig().getProgram().length); + if (size > benefit) + size -= benefit; + } + return size; + } + /** * A coinbase transaction is one that creates a new coin. They are the first transaction in each block and their * value is determined by a formula that all implementations of Bitcoin share. In 2011 the value of a coinbase diff --git a/core/src/test/java/org/bitcoinj/core/TransactionTest.java b/core/src/test/java/org/bitcoinj/core/TransactionTest.java index 9fe4dfbc..8cde9464 100644 --- a/core/src/test/java/org/bitcoinj/core/TransactionTest.java +++ b/core/src/test/java/org/bitcoinj/core/TransactionTest.java @@ -1,24 +1,16 @@ package org.bitcoinj.core; -import org.bitcoinj.core.TransactionConfidence.ConfidenceType; -import org.bitcoinj.params.UnitTestParams; -import org.bitcoinj.script.Script; -import org.bitcoinj.script.ScriptBuilder; -import org.bitcoinj.testing.FakeTxBuilder; -import org.junit.Before; -import org.junit.Test; -import org.easymock.EasyMock; +import org.bitcoinj.core.TransactionConfidence.*; +import org.bitcoinj.params.*; +import org.bitcoinj.script.*; +import org.bitcoinj.testing.*; +import org.easymock.*; +import org.junit.*; -import static org.junit.Assert.assertEquals; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.replay; +import java.util.*; -import java.util.Calendar; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.SortedSet; -import java.util.TreeSet; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; /** * Just check the Transaction.verify() method. Most methods that have complicated logic in Transaction are tested @@ -296,4 +288,18 @@ public class TransactionTest { tx.addSignedInput(fakeTx.getOutput(0).getOutPointFor(), script, key); } + + @Test + public void testPrioSizeCalc() throws Exception { + Transaction tx1 = FakeTxBuilder.createFakeTx(PARAMS, Coin.COIN, ADDRESS); + int size1 = tx1.getMessageSize(); + int size2 = tx1.getMessageSizeForPriorityCalc(); + assertEquals(113, size1 - size2); + tx1.getInput(0).setScriptSig(new Script(new byte[109])); + assertEquals(78, tx1.getMessageSizeForPriorityCalc()); + tx1.getInput(0).setScriptSig(new Script(new byte[110])); + assertEquals(78, tx1.getMessageSizeForPriorityCalc()); + tx1.getInput(0).setScriptSig(new Script(new byte[111])); + assertEquals(79, tx1.getMessageSizeForPriorityCalc()); + } } \ No newline at end of file