mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2024-11-20 18:22:12 +01:00
Clean up WalletTransaction and serialization code a bit.
This commit is contained in:
parent
b3673999d4
commit
f318808cf7
@ -1333,9 +1333,6 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
|
||||
case DEAD:
|
||||
checkState(dead.put(tx.getHash(), tx) == null);
|
||||
break;
|
||||
case PENDING_INACTIVE:
|
||||
checkState(pending.put(tx.getHash(), tx) == null);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown wallet transaction type " + pool);
|
||||
}
|
||||
@ -1459,8 +1456,6 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
|
||||
return pending.size();
|
||||
case DEAD:
|
||||
return dead.size();
|
||||
case ALL:
|
||||
return unspent.size() + spent.size() + pending.size() + dead.size();
|
||||
}
|
||||
throw new RuntimeException("Unreachable");
|
||||
} finally {
|
||||
|
@ -221,7 +221,7 @@ public class WalletProtobufSerializer {
|
||||
Transaction tx = wtx.getTransaction();
|
||||
Protos.Transaction.Builder txBuilder = Protos.Transaction.newBuilder();
|
||||
|
||||
txBuilder.setPool(Protos.Transaction.Pool.valueOf(wtx.getPool().getValue()))
|
||||
txBuilder.setPool(getProtoPool(wtx))
|
||||
.setHash(hashToByteString(tx.getHash()))
|
||||
.setVersion((int) tx.getVersion());
|
||||
|
||||
@ -288,6 +288,17 @@ public class WalletProtobufSerializer {
|
||||
return txBuilder.build();
|
||||
}
|
||||
|
||||
private static Protos.Transaction.Pool getProtoPool(WalletTransaction wtx) {
|
||||
switch (wtx.getPool()) {
|
||||
case UNSPENT: return Protos.Transaction.Pool.UNSPENT;
|
||||
case SPENT: return Protos.Transaction.Pool.SPENT;
|
||||
case DEAD: return Protos.Transaction.Pool.DEAD;
|
||||
case PENDING: return Protos.Transaction.Pool.PENDING;
|
||||
default:
|
||||
throw new RuntimeException("Unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeConfidence(Protos.Transaction.Builder txBuilder,
|
||||
TransactionConfidence confidence,
|
||||
Protos.TransactionConfidence.Builder confidenceBuilder) {
|
||||
@ -351,19 +362,15 @@ public class WalletProtobufSerializer {
|
||||
* @throws UnreadableWalletException thrown in various error conditions (see description).
|
||||
*/
|
||||
public Wallet readWallet(InputStream input) throws UnreadableWalletException {
|
||||
Protos.Wallet walletProto = null;
|
||||
try {
|
||||
walletProto = parseToProto(input);
|
||||
Protos.Wallet walletProto = parseToProto(input);
|
||||
NetworkParameters params = NetworkParameters.fromID(walletProto.getNetworkIdentifier());
|
||||
Wallet wallet = new Wallet(params);
|
||||
readWallet(walletProto, wallet);
|
||||
return wallet;
|
||||
} catch (IOException e) {
|
||||
throw new UnreadableWalletException("Could not load wallet file", e);
|
||||
throw new UnreadableWalletException("Could not parse input stream to protobuf", e);
|
||||
}
|
||||
|
||||
// System.out.println(TextFormat.printToString(walletProto));
|
||||
|
||||
NetworkParameters params = NetworkParameters.fromID(walletProto.getNetworkIdentifier());
|
||||
Wallet wallet = new Wallet(params);
|
||||
readWallet(walletProto, wallet);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -566,13 +573,22 @@ public class WalletProtobufSerializer {
|
||||
|
||||
private WalletTransaction connectTransactionOutputs(org.bitcoinj.wallet.Protos.Transaction txProto) throws UnreadableWalletException {
|
||||
Transaction tx = txMap.get(txProto.getHash());
|
||||
WalletTransaction.Pool pool = WalletTransaction.Pool.valueOf(txProto.getPool().getNumber());
|
||||
if (pool == WalletTransaction.Pool.INACTIVE || pool == WalletTransaction.Pool.PENDING_INACTIVE) {
|
||||
final WalletTransaction.Pool pool;
|
||||
switch (txProto.getPool()) {
|
||||
case DEAD: pool = WalletTransaction.Pool.DEAD; break;
|
||||
case PENDING: pool = WalletTransaction.Pool.PENDING; break;
|
||||
case SPENT: pool = WalletTransaction.Pool.SPENT; break;
|
||||
case UNSPENT: pool = WalletTransaction.Pool.UNSPENT; break;
|
||||
// Upgrade old wallets: inactive pool has been merged with the pending pool.
|
||||
// Remove this some time after 0.9 is old and everyone has upgraded.
|
||||
// There should not be any spent outputs in this tx as old wallets would not allow them to be spent
|
||||
// in this state.
|
||||
pool = WalletTransaction.Pool.PENDING;
|
||||
case INACTIVE:
|
||||
case PENDING_INACTIVE:
|
||||
pool = WalletTransaction.Pool.PENDING;
|
||||
break;
|
||||
default:
|
||||
throw new UnreadableWalletException("Unknown transaction pool: " + txProto.getPool());
|
||||
}
|
||||
for (int i = 0 ; i < tx.getOutputs().size() ; i++) {
|
||||
TransactionOutput output = tx.getOutputs().get(i);
|
||||
|
@ -16,60 +16,22 @@
|
||||
|
||||
package com.google.bitcoin.wallet;
|
||||
|
||||
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A Transaction in a Wallet - includes the pool ID
|
||||
*
|
||||
* @author Miron Cuperman
|
||||
* Stores data about a transaction that is only relevant to the {@link com.google.bitcoin.core.Wallet} class.
|
||||
*/
|
||||
public class WalletTransaction {
|
||||
/**
|
||||
* This is a bitfield oriented enum, with the following bits:
|
||||
*
|
||||
* <li>bit 0 - spent
|
||||
* <li>bit 1 - appears in alt chain
|
||||
* <li>bit 2 - appears in best chain
|
||||
* <li>bit 3 - double-spent
|
||||
* <li>bit 4 - pending (we would like the tx to go into the best chain)
|
||||
*
|
||||
* <p>Not all combinations are interesting, just the ones actually used in the enum.
|
||||
*/
|
||||
public enum Pool {
|
||||
UNSPENT(4), // unspent in best chain
|
||||
SPENT(5), // spent in best chain
|
||||
INACTIVE(2), // in alt chain
|
||||
DEAD(10), // double-spend in alt chain
|
||||
PENDING(16), // a pending tx we would like to go into the best chain
|
||||
PENDING_INACTIVE(18), // a pending tx in alt but not in best yet
|
||||
ALL(-1);
|
||||
|
||||
private int value;
|
||||
Pool(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Pool valueOf(int value) {
|
||||
switch (value) {
|
||||
case 4: return UNSPENT;
|
||||
case 5: return SPENT;
|
||||
case 2: return INACTIVE;
|
||||
case 10: return DEAD;
|
||||
case 16: return PENDING;
|
||||
case 18: return PENDING_INACTIVE;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
UNSPENT, // unspent in best chain
|
||||
SPENT, // spent in best chain
|
||||
DEAD, // double-spend in alt chain
|
||||
PENDING, // a pending tx we would like to go into the best chain
|
||||
}
|
||||
private Transaction transaction;
|
||||
private Pool pool;
|
||||
private final Transaction transaction;
|
||||
private final Pool pool;
|
||||
|
||||
public WalletTransaction(Pool pool, Transaction transaction) {
|
||||
this.pool = checkNotNull(pool);
|
||||
|
@ -161,7 +161,7 @@ public class WalletTest extends TestWithWallet {
|
||||
assertEquals("This ECKey is encrypted but no decryption key has been supplied.", kce.getMessage());
|
||||
}
|
||||
assertEquals("Wrong number of UNSPENT.1", 1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
assertEquals("Wrong number of ALL.1", 1, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals("Wrong number of ALL.1", 1, wallet.getTransactions(true).size());
|
||||
|
||||
// Try to create a send with a fee but the wrong password (this should fail).
|
||||
req = Wallet.SendRequest.to(destination, v2);
|
||||
@ -177,7 +177,7 @@ public class WalletTest extends TestWithWallet {
|
||||
}
|
||||
|
||||
assertEquals("Wrong number of UNSPENT.2", 1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
assertEquals("Wrong number of ALL.2", 1, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals("Wrong number of ALL.2", 1, wallet.getTransactions(true).size());
|
||||
|
||||
// Create a send with a fee with the correct password (this should succeed).
|
||||
req = Wallet.SendRequest.to(destination, v2);
|
||||
@ -191,7 +191,7 @@ public class WalletTest extends TestWithWallet {
|
||||
|
||||
Transaction t2 = req.tx;
|
||||
assertEquals("Wrong number of UNSPENT.3", 1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
assertEquals("Wrong number of ALL.3", 1, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals("Wrong number of ALL.3", 1, wallet.getTransactions(true).size());
|
||||
assertEquals(TransactionConfidence.Source.SELF, t2.getConfidence().getSource());
|
||||
assertEquals(Transaction.Purpose.USER_PAYMENT, t2.getPurpose());
|
||||
assertEquals(wallet.getChangeAddress(), t2.getOutput(1).getScriptPubKey().getToAddress(params));
|
||||
@ -230,7 +230,7 @@ public class WalletTest extends TestWithWallet {
|
||||
assertEquals("Incorrect confirmed tx balance", v1, wallet.getBalance());
|
||||
assertEquals("Incorrect confirmed tx PENDING pool size", 0, wallet.getPoolSize(WalletTransaction.Pool.PENDING));
|
||||
assertEquals("Incorrect confirmed tx UNSPENT pool size", 1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
assertEquals("Incorrect confirmed tx ALL pool size", 1, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals("Incorrect confirmed tx ALL pool size", 1, wallet.getTransactions(true).size());
|
||||
Threading.waitForUserCode();
|
||||
assertTrue(availFuture.isDone());
|
||||
assertTrue(estimatedFuture.isDone());
|
||||
@ -263,7 +263,7 @@ public class WalletTest extends TestWithWallet {
|
||||
Threading.waitForUserCode();
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.PENDING));
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.SPENT));
|
||||
assertEquals(2, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals(2, wallet.getTransactions(true).size());
|
||||
assertEquals(t, txns.getFirst());
|
||||
assertEquals(1, txns.size());
|
||||
}
|
||||
@ -296,7 +296,7 @@ public class WalletTest extends TestWithWallet {
|
||||
sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||
assertEquals(v1, wallet.getBalance());
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals(1, wallet.getTransactions(true).size());
|
||||
|
||||
ECKey k2 = new ECKey();
|
||||
Address a2 = k2.toAddress(params);
|
||||
@ -321,7 +321,7 @@ public class WalletTest extends TestWithWallet {
|
||||
wallet.commitTx(t2);
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.PENDING));
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.SPENT));
|
||||
assertEquals(2, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals(2, wallet.getTransactions(true).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -332,11 +332,11 @@ public class WalletTest extends TestWithWallet {
|
||||
sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||
assertEquals(v1, wallet.getBalance());
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals(1, wallet.getTransactions(true).size());
|
||||
|
||||
BigInteger v2 = toNanoCoins(0, 50);
|
||||
sendMoneyToWallet(v2, AbstractBlockChain.NewBlockType.SIDE_CHAIN);
|
||||
assertEquals(2, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals(2, wallet.getTransactions(true).size());
|
||||
assertEquals(v1, wallet.getBalance());
|
||||
assertEquals(v1.add(v2), wallet.getBalance(Wallet.BalanceType.ESTIMATED));
|
||||
}
|
||||
@ -347,7 +347,7 @@ public class WalletTest extends TestWithWallet {
|
||||
BigInteger v1 = toNanoCoins(5, 0);
|
||||
BigInteger v2 = toNanoCoins(0, 50);
|
||||
BigInteger expected = toNanoCoins(5, 50);
|
||||
assertEquals(0, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals(0, wallet.getTransactions(true).size());
|
||||
sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
sendMoneyToWallet(v2, AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||
@ -543,7 +543,7 @@ public class WalletTest extends TestWithWallet {
|
||||
// in the unspent pool, not pending or spent.
|
||||
BigInteger coinHalf = Utils.toNanoCoins(0, 50);
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals(1, wallet.getTransactions(true).size());
|
||||
Address someOtherGuy = new ECKey().toAddress(params);
|
||||
Transaction outbound1 = wallet.createSend(someOtherGuy, coinHalf);
|
||||
wallet.commitTx(outbound1);
|
||||
@ -899,7 +899,7 @@ public class WalletTest extends TestWithWallet {
|
||||
sendMoneyToWallet(coin1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||
// Send half to ourselves. We should then have a balance available to spend of zero.
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals(1, wallet.getTransactions(true).size());
|
||||
Transaction outbound1 = wallet.createSend(myAddress, coinHalf);
|
||||
wallet.commitTx(outbound1);
|
||||
// We should have a zero available balance before the next block.
|
||||
@ -1134,7 +1134,7 @@ public class WalletTest extends TestWithWallet {
|
||||
wallet.commitTx(t2);
|
||||
assertEquals(0, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.PENDING));
|
||||
assertEquals(2, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals(2, wallet.getTransactions(true).size());
|
||||
|
||||
// Now try to the spend the output.
|
||||
ECKey k3 = new ECKey();
|
||||
@ -1148,7 +1148,7 @@ public class WalletTest extends TestWithWallet {
|
||||
wallet.commitTx(t3);
|
||||
assertEquals(0, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
|
||||
assertEquals(2, wallet.getPoolSize(WalletTransaction.Pool.PENDING));
|
||||
assertEquals(3, wallet.getPoolSize(WalletTransaction.Pool.ALL));
|
||||
assertEquals(3, wallet.getTransactions(true).size());
|
||||
|
||||
// Now the output of t2 must not be available for spending
|
||||
assertFalse(o2.isAvailableForSpending());
|
||||
|
Loading…
Reference in New Issue
Block a user