Skip to content

Commit

Permalink
#154 plumbing for configurable feePerKB
Browse files Browse the repository at this point in the history
  • Loading branch information
jim618 committed Feb 22, 2015
1 parent 4725700 commit 65462a0
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
* <ul>
* <li>perform a lookup to the BRIT server to get the list of Bitcoin addresses fees need to be paid to</li>
* <li>provide the details of the next fee to be paid by the Payer</li>
* <li>the minimum, default and maximum feePerKB to use on spends in satoshi</li>
* </ul>
*
* @since 0.0.1
Expand All @@ -62,6 +63,10 @@ public class FeeService {

private static final Logger log = LoggerFactory.getLogger(FeeService.class);

public static final Coin MINIMUM_FEE_PER_KB = Coin.valueOf(1000); // The minimum relay fee as per Bitcoin Core 0.9
public static final Coin DEFAULT_FEE_PER_KB = Coin.valueOf(3000); // Logarithmically halfway ish between min and max
public static final Coin MAXIMUM_FEE_PER_KB = Coin.valueOf(10000); // 0.1 mBTC per KB - a long used fee structure

/**
* Always work with MainNet in BRIT (no access to wallet configuration)
*/
Expand Down Expand Up @@ -330,6 +335,29 @@ public FeeState calculateFeeState(Wallet wallet, boolean forceNow) {
return new FeeState(true, nextSendFeeAddress, currentNumberOfSends, nextSendFeeCount, FEE_PER_SEND, netFeeToBePaid);
}


/**
* Normalise the feePerKB so that it is always between the minimum and maximum values
* @param rawFeePerKB the raw value of feePerKB, as satoshi
* @return the normalised feePerKB, as Coin
*/
public static Coin normaliseRawFeePerKB(long rawFeePerKB) {
if (rawFeePerKB == 0) {
return DEFAULT_FEE_PER_KB;
}

if (Coin.valueOf(rawFeePerKB).compareTo(MINIMUM_FEE_PER_KB) < 0) {
return MINIMUM_FEE_PER_KB;
}

if (Coin.valueOf(rawFeePerKB).compareTo(MAXIMUM_FEE_PER_KB) > 0) {
return MAXIMUM_FEE_PER_KB;
}

// Ok as is
return Coin.valueOf(rawFeePerKB);
}

/**
* Get all the send transactions in the wallet that are sent by self
* (Sends that originate from another copy of this HD have no client fee attached)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,35 @@ public void testCalculateFeeState() throws Exception {
checkFeeState(feeState, true, NUMBER_OF_NON_FEE_SENDS + 1, Coin.ZERO, FeeService.FEE_PER_SEND, possibleNextFeeAddresses);
}

@Test
public void checkFeePerKB() {

// Check minimum
assertThat(Coin.valueOf(1000).equals(FeeService.MINIMUM_FEE_PER_KB)).isTrue();

// Check default
assertThat(Coin.valueOf(3000).equals(FeeService.DEFAULT_FEE_PER_KB)).isTrue();

// Check maximum
assertThat(Coin.valueOf(10000).equals(FeeService.MAXIMUM_FEE_PER_KB)).isTrue();

// Check normalisation logic

// Missing - set to default
assertThat(FeeService.DEFAULT_FEE_PER_KB.equals(FeeService.normaliseRawFeePerKB(0))).isTrue();

// Too small
assertThat(FeeService.MINIMUM_FEE_PER_KB.equals(FeeService.normaliseRawFeePerKB(-1))).isTrue();
assertThat(FeeService.MINIMUM_FEE_PER_KB.equals(FeeService.normaliseRawFeePerKB(999))).isTrue();

// Just right
assertThat(Coin.valueOf(1234).equals(FeeService.normaliseRawFeePerKB(1234))).isTrue();

// Too big
assertThat(FeeService.MAXIMUM_FEE_PER_KB.equals(FeeService.normaliseRawFeePerKB(10001))).isTrue();
assertThat(FeeService.MAXIMUM_FEE_PER_KB.equals(FeeService.normaliseRawFeePerKB(123456))).isTrue();
}

private void checkFeeState(
FeeState feeState,
boolean expectedIsUsingHardwiredBRITAddress,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package org.multibit.hd.core.config;

import org.multibit.hd.brit.services.FeeService;

/**
* <p>Configuration to provide the following to application:</p>
* <ul>
* <li>Configuration of current and available wallets</li>
* <li>Fee per KB to be used in spends</li>
* </ul>
*
* @since 0.0.1
Expand All @@ -23,6 +26,12 @@ public class WalletConfiguration {
*/
private String recentWalletLabel;

/**
* The fee per kilobyte of transaction to use in spends
* Note feePerKB is a long rather than a Coin as Coin does not round trip as is via JSON
*/
private long feePerKB = FeeService.DEFAULT_FEE_PER_KB.longValue();


/**
* @return The last/current soft wallet root (e.g. "mbhd-11111111-22222222-33333333-44444444-55555555")
Expand Down Expand Up @@ -56,6 +65,14 @@ public void setRecentWalletLabel(String recentWalletLabel) {
this.recentWalletLabel = recentWalletLabel;
}

public long getFeePerKB() {
return feePerKB;
}

public void setFeePerKB(long feePerKB) {
this.feePerKB = feePerKB;
}

/**
* @return A deep copy of this object
*/
Expand All @@ -66,8 +83,8 @@ public WalletConfiguration deepCopy() {
configuration.setLastSoftWalletRoot(getLastSoftWalletRoot());
configuration.setRecentWalletDataValidity(getRecentWalletDataValidity());
configuration.setRecentWalletLabel(getRecentWalletLabel());
configuration.setFeePerKB(getFeePerKB());

return configuration;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ public class BitcoinNetworkService extends AbstractService {

private static final Logger log = LoggerFactory.getLogger(BitcoinNetworkService.class);

public static final Coin DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; // Currently 1,000 satoshi
public static final int MAXIMUM_NUMBER_OF_PEERS = 6;

private static final int SIZE_OF_SIGNATURE = 72; // bytes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.bitcoinj.crypto.TransactionSignature;
import org.bitcoinj.params.MainNetParams;
import org.multibit.hd.brit.dto.FeeState;
import org.multibit.hd.brit.services.FeeService;
import org.multibit.hd.core.config.BitcoinConfiguration;
import org.multibit.hd.core.config.Configurations;
import org.multibit.hd.core.config.LanguageConfiguration;
Expand Down Expand Up @@ -250,7 +251,7 @@ private boolean prepareTransaction() {
coinAmount.or(Coin.ZERO),
fiatPayment,
changeAddress,
BitcoinNetworkService.DEFAULT_FEE_PER_KB,
FeeService.normaliseRawFeePerKB(Configurations.currentConfiguration.getWallet().getFeePerKB()),
password,
feeState,
true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.uri.BitcoinURI;
import org.multibit.hd.brit.dto.FeeState;
import org.multibit.hd.brit.services.FeeService;
import org.multibit.hd.core.config.BitcoinConfiguration;
import org.multibit.hd.core.config.Configurations;
import org.multibit.hd.core.config.LanguageConfiguration;
Expand Down Expand Up @@ -284,7 +285,7 @@ private boolean prepareTransaction() {
coin,
fiatPayment,
changeAddress,
BitcoinNetworkService.DEFAULT_FEE_PER_KB,
FeeService.normaliseRawFeePerKB(Configurations.currentConfiguration.getWallet().getFeePerKB()),
null,
feeState,
false);
Expand Down

0 comments on commit 65462a0

Please sign in to comment.