3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-11 17:55:53 +00:00

Add a getValueSentFromMe() to complement getValueSentToMe() and some unit tests.

BUG=2
This commit is contained in:
Mike Hearn 2011-03-12 17:57:37 +00:00
parent 99d155e0fe
commit 29e60a460d
4 changed files with 73 additions and 15 deletions

View File

@ -98,9 +98,11 @@ public class Transaction extends Message implements Serializable {
}
/**
* Returns the sum of the outputs that are sending coins to a key in our wallet.
* Calculates the sum of the outputs that are sending coins to a key in the wallet.
* @return sum in nanocoins
*/
public BigInteger getValueSentToMe(Wallet wallet) {
// This is tested in WalletTest.
BigInteger v = BigInteger.ZERO;
for (TransactionOutput o : outputs) {
if (o.isMine(wallet)) {
@ -110,6 +112,28 @@ public class Transaction extends Message implements Serializable {
return v;
}
/**
* Calculates the sum of the inputs that are spending coins with keys in the wallet. This requires the
* transactions sending coins to those keys to be in the wallet. This method will not attempt to download the
* blocks containing the input transactions if the key is in the wallet but the transactions are not.
*
* @return sum in nanocoins.
*/
public BigInteger getValueSentFromMe(Wallet wallet) throws ScriptException {
// This is tested in WalletTest.
BigInteger v = BigInteger.ZERO;
for (TransactionInput input : inputs) {
boolean connected = input.outpoint.connect(wallet.unspent) ||
input.outpoint.connect(wallet.fullySpent);
if (connected) {
// This input is taking value from an transaction in our wallet. To discover the value,
// we must find the connected transaction.
v = v.add(input.outpoint.getConnectedOutput().getValue());
}
}
return v;
}
/**
* These constants are a part of a scriptSig signature on the inputs. They define the details of how a
* transaction can be redeemed, specifically, they control how the hash of the transaction is calculated.
@ -223,7 +247,7 @@ public class Transaction extends Message implements Serializable {
/**
* Once a transaction has some inputs and outputs added, the signatures in the inputs can be calculated. The
* signature is over the transaction itself, to prove the redeemer actually created that transaction,
* so we have to do this step last.
* so we have to do this step last.<p>
*
* This method is similar to SignatureHash in script.cpp
*

View File

@ -19,15 +19,16 @@ package com.google.bitcoin.core;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
/**
* This message is effectively a reference or pointer to a transaction output.
* This message is a reference or pointer to an output of a different transaction.
*/
public class TransactionOutPoint extends Message implements Serializable {
// ID of the transaction to which we refer.
/** Hash of the transaction to which we refer. */
byte[] hash;
// Which output of that transaction we are talking about.
/** Which output of that transaction we are talking about. */
long index;
// This is not part of bitcoin serialization.
@ -63,6 +64,21 @@ public class TransactionOutPoint extends Message implements Serializable {
Utils.uint32ToByteStreamLE(index, stream);
}
/**
* Scans the list for the transaction this outpoint refers to, and sets up the internal reference used by
* getConnectedOutput().
* @return true if connection took place, false if the referenced transaction was not in the list.
*/
boolean connect(List<Transaction> transactions) {
for (Transaction tx : transactions) {
if (Arrays.equals(tx.getHash(), hash)) {
fromTx = tx;
return true;
}
}
return false;
}
/**
* If this transaction was created using the explicit constructor rather than deserialized,
* retrieves the connected output transaction. Asserts if there is no connected transaction.

View File

@ -35,17 +35,21 @@ import java.util.List;
public class Wallet implements Serializable {
private static final long serialVersionUID = -4501424466753895784L;
// A list of transactions with outputs we can spend. Note that some of these transactions may be partially spent,
// that is, they have outputs some of which are redeemed and others which aren't already. The spentness of each
// output is tracked in the TransactionOutput object. The value of all unspent outputs is the balance of the
// wallet.
/**
* A list of transactions with outputs we can spend. Note that some of these transactions may be partially spent,
* that is, they have outputs some of which are redeemed and others which aren't already. The spentness of each
* output is tracked in the TransactionOutput object. The value of all unspent outputs is the balance of the
* wallet.
*/
public final ArrayList<Transaction> unspent;
// When all the outputs of a transaction are spent, it gets put here. These transactions aren't useful for
// anything except record keeping and presentation to the user.
private final LinkedList<Transaction> fullySpent;
/**
* When all the outputs of a transaction are spent, it gets put here. These transactions aren't useful for
* anything except record keeping and presentation to the user.
*/
final LinkedList<Transaction> fullySpent;
// A list of public/private EC keys owned by this user.
/** A list of public/private EC keys owned by this user. */
public final ArrayList<ECKey> keychain;
private final NetworkParameters params;
@ -320,7 +324,8 @@ public class Wallet implements Serializable {
/**
* Locates a keypair from the keychain given the hash of the public key. This is needed when finding out which
* key we need to use to redeem a transaction output. Returns null if no key was found.
* key we need to use to redeem a transaction output.
* @return ECKey object or null if no such key was found.
*/
public synchronized ECKey findKeyFromPubHash(byte[] pubkeyHash) {
for (ECKey key : keychain) {

View File

@ -138,4 +138,17 @@ public class WalletTest {
wallet.confirmSend(send2);
assertEquals(bitcoinValueToFriendlyString(wallet.getBalance()), "0.80");
}
@Test
public void testBalances() throws Exception {
BigInteger nanos = Utils.toNanoCoins(1, 0);
Transaction tx1 = createFakeTx(nanos, myAddress);
wallet.receive(tx1);
assertEquals(nanos, tx1.getValueSentToMe(wallet));
// Send 0.10 to somebody else.
Transaction send1 = wallet.createSend(new ECKey().toAddress(params), toNanoCoins(0, 10), myAddress);
// Reserialize.
Transaction send2 = new Transaction(params, send1.bitcoinSerialize());
assertEquals(nanos, send2.getValueSentFromMe(wallet));
}
}