Skip to content

Commit 112aeca

Browse files
committed
More tests ported. Paranoia checkin.
- Lots of new tests ported over. They are mostly working, but I'm checking in the code because paranoia.
1 parent ad4bee6 commit 112aeca

19 files changed

+1722
-172
lines changed

src/main/java/org/twostack/bitcoin/ECKey.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1108,9 +1108,9 @@ public String getPublicKeyAsHex() {
11081108
return Utils.HEX.encode(pub.getEncoded());
11091109
}
11101110

1111-
// public String getPrivateKeyAsWiF(NetworkParameters params) {
1112-
// return getPrivateKeyEncoded(params).toString();
1113-
// }
1111+
public String getPrivateKeyAsWiF(NetworkType networkType) {
1112+
return getPrivateKeyEncoded(networkType).toString();
1113+
}
11141114

11151115
private String toString(boolean includePrivate, @Nullable KeyParameter aesKey, @Nullable NetworkParameters params) {
11161116
final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(this).omitNullValues();

src/main/java/org/twostack/bitcoin/address/LegacyAddress.java

+31-12
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,28 @@ public class LegacyAddress extends Address {
4747
*/
4848
public static final int LENGTH = 20;
4949

50+
/** True if P2SH, false if P2PKH. */
51+
public final boolean p2sh;
52+
5053

5154
/**
5255
* Private constructor. Use {@link #fromBase58(NetworkAddressType, String)},
53-
* {@link #fromPubKeyHash(NetworkAddressType, byte[])},
56+
* {@link #fromPubKeyHash(NetworkAddressType, byte[])}, {@link #fromScriptHash(NetworkAddressType, byte[])} or
5457
* {@link #fromKey(NetworkAddressType, PublicKey)}.
55-
*
56-
* @param networkAddressType
58+
*
59+
* @param addressType
5760
* network this address is valid for
61+
* @param p2sh
62+
* true if hash160 is hash of a script, false if it is hash of a pubkey
5863
* @param hash160
5964
* 20-byte hash of pubkey or script
6065
*/
61-
private LegacyAddress(NetworkAddressType networkAddressType, byte[] hash160) throws AddressFormatException {
62-
super(networkAddressType, hash160);
66+
private LegacyAddress(NetworkAddressType addressType, boolean p2sh, byte[] hash160) throws AddressFormatException {
67+
super(addressType, hash160);
6368
if (hash160.length != 20)
6469
throw new AddressFormatException.InvalidDataLength(
6570
"Legacy addresses are 20 byte (160 bit) hashes, but got: " + hash160.length);
71+
this.p2sh = p2sh;
6672
}
6773

6874
/**
@@ -76,7 +82,7 @@ private LegacyAddress(NetworkAddressType networkAddressType, byte[] hash160) thr
7682
* @return constructed address
7783
*/
7884
public static LegacyAddress fromPubKeyHash(NetworkAddressType networkAddressType, byte[] hash160) throws AddressFormatException {
79-
return new LegacyAddress(networkAddressType, hash160);
85+
return new LegacyAddress(networkAddressType, false, hash160);
8086
}
8187

8288
/**
@@ -96,15 +102,15 @@ public static LegacyAddress fromKey(NetworkAddressType networkAddressType, Publi
96102
/**
97103
* Construct a {@link LegacyAddress} that represents the given P2SH script hash.
98104
*
99-
* @param networkType
105+
* @param networkAddressType
100106
* network this address is valid for
101107
* @param hash160
102108
* P2SH script hash
103109
* @return constructed address
104110
*/
105-
// public static LegacyAddress fromScriptHash(NetworkAddressType networkAddressType, byte[] hash160) throws AddressFormatException {
106-
// return new LegacyAddress(networkType, true, hash160);
107-
// }
111+
public static LegacyAddress fromScriptHash(NetworkAddressType networkAddressType, byte[] hash160) throws AddressFormatException {
112+
return new LegacyAddress(networkAddressType, true, hash160);
113+
}
108114

109115
/**
110116
* Construct a {@link LegacyAddress} from its base58 form.
@@ -127,9 +133,9 @@ public static LegacyAddress fromBase58(@Nullable NetworkAddressType networkAddre
127133

128134
if (networkAddressType == null) {
129135
NetworkAddressType derivedType = NetworkParameters.getNetworkAddressType(version);
130-
return new LegacyAddress(derivedType, bytes);
136+
return new LegacyAddress(derivedType, false, bytes);
131137
} else {
132-
return new LegacyAddress(networkAddressType, bytes);
138+
return new LegacyAddress(networkAddressType, true, bytes);
133139
}
134140

135141
}
@@ -173,6 +179,19 @@ public ScriptType getOutputScriptType() {
173179
}
174180
}
175181

182+
183+
/**
184+
* Given an address, examines the version byte and attempts to find a matching NetworkParameters. If you aren't sure
185+
* which network the address is intended for (eg, it was provided by a user), you can use this to decide if it is
186+
* compatible with the current wallet.
187+
*
188+
* @return network the address is valid for
189+
* @throws AddressFormatException if the given base58 doesn't parse or the checksum is invalid
190+
*/
191+
public static NetworkAddressType getNetworkFromAddress(String address) throws AddressFormatException {
192+
return LegacyAddress.fromBase58(null, address).networkAddressType;
193+
}
194+
176195
/**
177196
* Given an address, examines the version byte and attempts to find a matching NetworkParameters. If you aren't sure
178197
* which network the address is intended for (eg, it was provided by a user), you can use this to decide if it is

src/main/java/org/twostack/bitcoin/script/ScriptBuilder.java

-150
Original file line numberDiff line numberDiff line change
@@ -260,156 +260,6 @@ else if (scriptType == ScriptType.P2SH)
260260
}
261261
}
262262

263-
/**
264-
* Creates a scriptSig that can redeem a P2PKH output.
265-
* If given signature is null, incomplete scriptSig will be created with OP_0 instead of signature
266-
*/
267-
// public static Script createInputScript(@Nullable TransactionSignature signature, ECKey pubKey) {
268-
// byte[] pubkeyBytes = pubKey.getPubKey();
269-
// byte[] sigBytes = signature != null ? signature.encodeToBitcoin() : new byte[]{};
270-
// return new ScriptBuilder().data(sigBytes).data(pubkeyBytes).build();
271-
// }
272-
273-
/**
274-
* Creates a scriptSig that can redeem a P2PK output.
275-
* If given signature is null, incomplete scriptSig will be created with OP_0 instead of signature
276-
*/
277-
// public static Script createInputScript(@Nullable TransactionSignature signature) {
278-
// byte[] sigBytes = signature != null ? signature.encodeToBitcoin() : new byte[]{};
279-
// return new ScriptBuilder().data(sigBytes).build();
280-
// }
281-
282-
/** Creates a program that requires at least N of the given keys to sign, using OP_CHECKMULTISIG. */
283-
// public static Script createMultiSigOutputScript(int threshold, List<ECKey> pubkeys) {
284-
// checkArgument(threshold > 0);
285-
// checkArgument(threshold <= pubkeys.size());
286-
// checkArgument(pubkeys.size() <= 16); // That's the max we can represent with a single opcode.
287-
// ScriptBuilder builder = new ScriptBuilder();
288-
// builder.smallNum(threshold);
289-
// for (ECKey key : pubkeys) {
290-
// builder.data(key.getPubKey());
291-
// }
292-
// builder.smallNum(pubkeys.size());
293-
// builder.op(OP_CHECKMULTISIG);
294-
// return builder.build();
295-
// }
296-
297-
/** Create a program that satisfies an OP_CHECKMULTISIG program. */
298-
// public static Script createMultiSigInputScript(List<TransactionSignature> signatures) {
299-
// List<byte[]> sigs = new ArrayList<>(signatures.size());
300-
// for (TransactionSignature signature : signatures) {
301-
// sigs.add(signature.encodeToBitcoin());
302-
// }
303-
//
304-
// return createMultiSigInputScriptBytes(sigs, null);
305-
// }
306-
307-
/** Create a program that satisfies an OP_CHECKMULTISIG program. */
308-
// public static Script createMultiSigInputScript(TransactionSignature... signatures) {
309-
// return createMultiSigInputScript(Arrays.asList(signatures));
310-
// }
311-
312-
/** Create a program that satisfies an OP_CHECKMULTISIG program, using pre-encoded signatures. */
313-
// public static Script createMultiSigInputScriptBytes(List<byte[]> signatures) {
314-
// return createMultiSigInputScriptBytes(signatures, null);
315-
// }
316-
317-
/**
318-
* Create a program that satisfies a P2SH OP_CHECKMULTISIG program.
319-
* If given signature list is null, incomplete scriptSig will be created with OP_0 instead of signatures
320-
*/
321-
// public static Script createP2SHMultiSigInputScript(@Nullable List<TransactionSignature> signatures,
322-
// Script multisigProgram) {
323-
// List<byte[]> sigs = new ArrayList<>();
324-
// if (signatures == null) {
325-
// // create correct number of empty signatures
326-
// int numSigs = multisigProgram.getNumberOfSignaturesRequiredToSpend();
327-
// for (int i = 0; i < numSigs; i++)
328-
// sigs.add(new byte[]{});
329-
// } else {
330-
// for (TransactionSignature signature : signatures) {
331-
// sigs.add(signature.encodeToBitcoin());
332-
// }
333-
// }
334-
// return createMultiSigInputScriptBytes(sigs, multisigProgram.getProgram());
335-
// }
336-
337-
/**
338-
* Create a program that satisfies an OP_CHECKMULTISIG program, using pre-encoded signatures.
339-
* Optionally, appends the script program bytes if spending a P2SH output.
340-
*/
341-
// public static Script createMultiSigInputScriptBytes(List<byte[]> signatures, @Nullable byte[] multisigProgramBytes) {
342-
// checkArgument(signatures.size() <= 16);
343-
// ScriptBuilder builder = new ScriptBuilder();
344-
// builder.smallNum(0); // Work around a bug in CHECKMULTISIG that is now a required part of the protocol.
345-
// for (byte[] signature : signatures)
346-
// builder.data(signature);
347-
// if (multisigProgramBytes!= null)
348-
// builder.data(multisigProgramBytes);
349-
// return builder.build();
350-
// }
351-
352-
/**
353-
* Returns a copy of the given scriptSig with the signature inserted in the given position.
354-
*
355-
* This function assumes that any missing sigs have OP_0 placeholders. If given scriptSig already has all the signatures
356-
* in place, IllegalArgumentException will be thrown.
357-
*
358-
* @param targetIndex where to insert the signature
359-
* @param sigsPrefixCount how many items to copy verbatim (e.g. initial OP_0 for multisig)
360-
* @param sigsSuffixCount how many items to copy verbatim at end (e.g. redeemScript for P2SH)
361-
*/
362-
// public static Script updateScriptWithSignature(Script scriptSig, byte[] signature, int targetIndex,
363-
// int sigsPrefixCount, int sigsSuffixCount) {
364-
// ScriptBuilder builder = new ScriptBuilder();
365-
// List<ScriptChunk> inputChunks = scriptSig.getChunks();
366-
// int totalChunks = inputChunks.size();
367-
//
368-
// // Check if we have a place to insert, otherwise just return given scriptSig unchanged.
369-
// // We assume here that OP_0 placeholders always go after the sigs, so
370-
// // to find if we have sigs missing, we can just check the chunk in latest sig position
371-
// boolean hasMissingSigs = inputChunks.get(totalChunks - sigsSuffixCount - 1).equalsOpCode(OP_0);
372-
// checkArgument(hasMissingSigs, "ScriptSig is already filled with signatures");
373-
//
374-
// // copy the prefix
375-
// for (ScriptChunk chunk: inputChunks.subList(0, sigsPrefixCount))
376-
// builder.addChunk(chunk);
377-
//
378-
// // copy the sigs
379-
// int pos = 0;
380-
// boolean inserted = false;
381-
// for (ScriptChunk chunk: inputChunks.subList(sigsPrefixCount, totalChunks - sigsSuffixCount)) {
382-
// if (pos == targetIndex) {
383-
// inserted = true;
384-
// builder.data(signature);
385-
// pos++;
386-
// }
387-
// if (!chunk.equalsOpCode(OP_0)) {
388-
// builder.addChunk(chunk);
389-
// pos++;
390-
// }
391-
// }
392-
//
393-
// // add OP_0's if needed, since we skipped them in the previous loop
394-
// while (pos < totalChunks - sigsPrefixCount - sigsSuffixCount) {
395-
// if (pos == targetIndex) {
396-
// inserted = true;
397-
// builder.data(signature);
398-
// }
399-
// else {
400-
// builder.addChunk(new ScriptChunk(OP_0, null));
401-
// }
402-
// pos++;
403-
// }
404-
//
405-
// // copy the suffix
406-
// for (ScriptChunk chunk: inputChunks.subList(totalChunks - sigsSuffixCount, totalChunks))
407-
// builder.addChunk(chunk);
408-
//
409-
// checkState(inserted);
410-
// return builder.build();
411-
// }
412-
413263
/** Creates a scriptPubKey that encodes payment to the given raw public key. */
414264
public static Script createP2PKOutputScript(byte[] pubKey) {
415265
return new ScriptBuilder().data(pubKey).op(OP_CHECKSIG).build();

0 commit comments

Comments
 (0)