UTXOProvider: getOpenTransactionOutputs() to take a list of ECKeys rather than addresses.

This commit is contained in:
Andreas Schildbach 2018-03-01 17:16:31 +01:00
parent d92dfdfd14
commit 2c768bfe07
7 changed files with 19 additions and 22 deletions

View File

@ -25,15 +25,13 @@ import java.util.List;
* <p>A {@link org.bitcoinj.store.FullPrunedBlockStore} is an internal implementation within bitcoinj.</p>
*/
public interface UTXOProvider {
// TODO currently the access to outputs is by address. Change to ECKey
/**
* Get the list of {@link UTXO}'s for a given address.
* @param addresses List of address.
* Get the list of {@link UTXO}'s for given keys.
* @param keys List of keys.
* @return The list of transaction outputs.
* @throws UTXOProviderException If there is an error.
*/
List<UTXO> getOpenTransactionOutputs(List<LegacyAddress> addresses) throws UTXOProviderException;
List<UTXO> getOpenTransactionOutputs(List<ECKey> keys) throws UTXOProviderException;
/**
* Get the height of the chain head.

View File

@ -1150,14 +1150,15 @@ public abstract class DatabaseFullPrunedBlockStore implements FullPrunedBlockSto
}
@Override
public List<UTXO> getOpenTransactionOutputs(List<LegacyAddress> addresses) throws UTXOProviderException {
public List<UTXO> getOpenTransactionOutputs(List<ECKey> keys) throws UTXOProviderException {
PreparedStatement s = null;
List<UTXO> outputs = new ArrayList<>();
try {
maybeConnect();
s = conn.get().prepareStatement(getTransactionOutputSelectSQL());
for (LegacyAddress address : addresses) {
s.setString(1, address.toString());
for (ECKey key : keys) {
// TODO switch to pubKeyHash in order to support native segwit addresses
s.setString(1, LegacyAddress.fromKey(params, key).toString());
ResultSet rs = s.executeQuery();
while (rs.next()) {
Sha256Hash hash = Sha256Hash.wrap(rs.getBytes(1));

View File

@ -30,6 +30,7 @@ import java.nio.ByteBuffer;
import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.StoredBlock;
@ -420,16 +421,16 @@ public class LevelDBFullPrunedBlockStore implements FullPrunedBlockStore {
}
@Override
public List<UTXO> getOpenTransactionOutputs(List<LegacyAddress> addresses) throws UTXOProviderException {
public List<UTXO> getOpenTransactionOutputs(List<ECKey> keys) throws UTXOProviderException {
// Run this on a snapshot of database so internally consistent result
// This is critical or if one address paid another could get incorrect
// results
List<UTXO> results = new LinkedList<>();
for (LegacyAddress a : addresses) {
for (ECKey key : keys) {
ByteBuffer bb = ByteBuffer.allocate(21);
bb.put((byte) KeyType.ADDRESS_HASHINDEX.ordinal());
bb.put(a.getHash());
bb.put(key.getPubKeyHash());
ReadOptions ro = new ReadOptions();
Snapshot sn = db.getSnapshot();
@ -443,7 +444,7 @@ public class LevelDBFullPrunedBlockStore implements FullPrunedBlockStore {
bbKey.get(); // remove the address_hashindex byte.
byte[] addressKey = new byte[20];
bbKey.get(addressKey);
if (!Arrays.equals(addressKey, a.getHash())) {
if (!Arrays.equals(addressKey, key.getPubKeyHash())) {
break;
}
byte[] hashBytes = new byte[32];

View File

@ -412,13 +412,15 @@ public class MemoryFullPrunedBlockStore implements FullPrunedBlockStore {
}
@Override
public List<UTXO> getOpenTransactionOutputs(List<LegacyAddress> addresses) throws UTXOProviderException {
public List<UTXO> getOpenTransactionOutputs(List<ECKey> keys) throws UTXOProviderException {
// This is *NOT* optimal: We go through all the outputs and select the ones we are looking for.
// If someone uses this store for production then they have a lot more to worry about than an inefficient impl :)
List<UTXO> foundOutputs = new ArrayList<>();
List<UTXO> outputsList = transactionOutputMap.values();
for (UTXO output : outputsList) {
for (LegacyAddress address : addresses) {
for (ECKey key : keys) {
// TODO switch to pubKeyHash in order to support native segwit addresses
Address address = LegacyAddress.fromKey(params, key);
if (output.getAddress().equals(address.toString())) {
foundOutputs.add(output);
}

View File

@ -4300,12 +4300,7 @@ public class Wallet extends BaseTaggableObject
List<UTXO> candidates = new ArrayList<>();
List<ECKey> keys = getImportedKeys();
keys.addAll(getActiveKeyChain().getLeafKeys());
List<LegacyAddress> addresses = new ArrayList<>();
for (ECKey key : keys) {
LegacyAddress address = LegacyAddress.fromKey(params, key);
addresses.add(address);
}
candidates.addAll(utxoProvider.getOpenTransactionOutputs(addresses));
candidates.addAll(utxoProvider.getOpenTransactionOutputs(keys));
return candidates;
}

View File

@ -272,7 +272,7 @@ public abstract class AbstractFullPrunedBlockChainTest {
chain.add(rollingBlock);
totalAmount = totalAmount.add(amount);
List<UTXO> outputs = store.getOpenTransactionOutputs(Lists.newArrayList(address));
List<UTXO> outputs = store.getOpenTransactionOutputs(Lists.newArrayList(toKey));
assertNotNull(outputs);
assertEquals("Wrong Number of Outputs", 1, outputs.size());
UTXO output = outputs.get(0);

View File

@ -69,7 +69,7 @@ public class TransactionInputTest {
}
@Override
public List<UTXO> getOpenTransactionOutputs(List<LegacyAddress> addresses) throws UTXOProviderException {
public List<UTXO> getOpenTransactionOutputs(List<ECKey> addresses) throws UTXOProviderException {
return Lists.newArrayList(utxo);
}