diff --git a/core/build.gradle b/core/build.gradle
index 790bda488de..866bcf973eb 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -3,23 +3,22 @@ apply plugin: 'com.google.protobuf'
apply plugin: 'maven'
apply plugin: 'eclipse'
-version = '0.15.2'
+version = '0.15.5'
archivesBaseName = 'groestlcoinj-core'
eclipse.project.name = 'groestlcoinj-core'
dependencies {
- compile 'org.bouncycastle:bcprov-jdk15on:1.60'
- implementation 'com.lambdaworks:scrypt:1.4.0'
- implementation 'com.google.guava:guava:27.0.1-android'
+ compile 'org.bouncycastle:bcprov-jdk15to18:1.63'
+ implementation 'com.google.guava:guava:27.1-android'
compile 'com.google.protobuf:protobuf-java:3.6.1'
- implementation 'com.squareup.okhttp3:okhttp:3.12.1'
- implementation 'org.slf4j:slf4j-api:1.7.25'
+ implementation 'com.squareup.okhttp3:okhttp:3.12.3'
+ implementation 'org.slf4j:slf4j-api:1.7.28'
implementation 'net.jcip:jcip-annotations:1.0'
compileOnly 'org.fusesource.leveldbjni:leveldbjni-all:1.8'
testImplementation 'junit:junit:4.12'
testImplementation 'org.easymock:easymock:3.2'
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.5.2'
- testImplementation 'org.slf4j:slf4j-jdk14:1.7.25'
+ testImplementation 'org.slf4j:slf4j-jdk14:1.7.28'
testImplementation 'com.h2database:h2:1.3.167'
testImplementation 'org.fusesource.leveldbjni:leveldbjni-all:1.8'
}
@@ -27,6 +26,7 @@ dependencies {
sourceCompatibility = 1.7
compileJava.options.encoding = 'UTF-8'
compileTestJava.options.encoding = 'UTF-8'
+javadoc.options.encoding = 'UTF-8'
protobuf {
protoc {
diff --git a/core/src/main/java/org/bitcoinj/core/AbstractBlockChain.java b/core/src/main/java/org/bitcoinj/core/AbstractBlockChain.java
index 19422223361..6fc6de00d8f 100644
--- a/core/src/main/java/org/bitcoinj/core/AbstractBlockChain.java
+++ b/core/src/main/java/org/bitcoinj/core/AbstractBlockChain.java
@@ -69,8 +69,8 @@
* we say it is an orphan chain. Orphan chains can occur when blocks are solved and received during the initial block
* chain download, or if we connect to a peer that doesn't send us blocks in order.
*
- * A reorganize occurs when the blocks that make up the best known chain changes. Note that simply adding a
- * new block to the top of the best chain isn't as reorganize, but that a reorganize is always triggered by adding
+ *
A reorganize occurs when the blocks that make up the best known chain change. Note that simply adding a
+ * new block to the top of the best chain isn't a reorganize, but that a reorganize is always triggered by adding
* a new block that connects to some other (non best head) block. By "best" we mean the chain representing the largest
* amount of work done.
*
@@ -543,7 +543,8 @@ private void connectBlock(final Block block, StoredBlock storedPrev, boolean exp
block.transactions == null ? block : block.cloneAsHeader(), txOutChanges);
versionTally.add(block.getVersion());
setChainHead(newStoredBlock);
- log.debug("Chain is now {} blocks high, running listeners", newStoredBlock.getHeight());
+ if (log.isDebugEnabled())
+ log.debug("Chain is now {} blocks high, running listeners", newStoredBlock.getHeight());
informListenersForNewBlock(block, NewBlockType.BEST_CHAIN, filteredTxHashList, filteredTxn, newStoredBlock);
} else {
// This block connects to somewhere other than the top of the best known chain. We treat these differently.
@@ -898,7 +899,8 @@ private void tryConnectingOrphans() throws VerificationException, BlockStoreExce
StoredBlock prev = getStoredBlockInCurrentScope(orphanBlock.block.getPrevBlockHash());
if (prev == null) {
// This is still an unconnected/orphan block.
- log.debug("Orphan block {} is not connectable right now", orphanBlock.block.getHash());
+ if (log.isDebugEnabled())
+ log.debug("Orphan block {} is not connectable right now", orphanBlock.block.getHash());
continue;
}
// Otherwise we can connect it now.
@@ -1042,7 +1044,7 @@ void trackFalsePositives(int count) {
// Track false positives in batch by adding alpha to the false positive estimate once per count.
// Each false positive counts as 1.0 towards the estimate.
falsePositiveRate += FP_ESTIMATOR_ALPHA * count;
- if (count > 0)
+ if (count > 0 && log.isDebugEnabled())
log.debug("{} false positives, current rate = {} trend = {}", count, falsePositiveRate, falsePositiveTrend);
}
diff --git a/core/src/main/java/org/bitcoinj/core/ECKey.java b/core/src/main/java/org/bitcoinj/core/ECKey.java
index 0144ebf7f81..6572b061570 100644
--- a/core/src/main/java/org/bitcoinj/core/ECKey.java
+++ b/core/src/main/java/org/bitcoinj/core/ECKey.java
@@ -148,7 +148,7 @@ public int compare(ECKey k1, ECKey k2) {
// The two parts of the key. If "priv" is set, "pub" can always be calculated. If "pub" is set but not "priv", we
// can only verify signatures not make them.
- protected final BigInteger priv; // A field element.
+ @Nullable protected final BigInteger priv; // A field element.
protected final LazyECPoint pub;
// Creation time of the key in seconds since the epoch, or zero if the key was deserialized from a version that did
@@ -992,7 +992,7 @@ public static ECKey recoverFromSignature(int recId, ECDSASignature sig, Sha256Ha
// 1.2. Convert the integer x to an octet string X of length mlen using the conversion routine
// specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉.
// 1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R using the
- // conversion routine specified in Section 2.3.4. If this conversion routine outputs “invalid”, then
+ // conversion routine specified in Section 2.3.4. If this conversion routine outputs "invalid", then
// do another iteration of Step 1.
//
// More concisely, what these points mean is to use X as a compressed public key.
diff --git a/core/src/main/java/org/bitcoinj/core/Peer.java b/core/src/main/java/org/bitcoinj/core/Peer.java
index a8cbcb2847e..87531b7a175 100644
--- a/core/src/main/java/org/bitcoinj/core/Peer.java
+++ b/core/src/main/java/org/bitcoinj/core/Peer.java
@@ -575,7 +575,8 @@ private void processVersionMessage(VersionMessage m) throws ProtocolException {
// Now it's our turn ...
// Send an ACK message stating we accept the peers protocol version.
sendMessage(new VersionAck());
- log.debug("{}: Incoming version handshake complete.", this);
+ if (log.isDebugEnabled())
+ log.debug("{}: Incoming version handshake complete.", this);
incomingVersionHandshakeFuture.set(this);
}
@@ -586,12 +587,14 @@ private void processVersionAck(VersionAck m) throws ProtocolException {
if (outgoingVersionHandshakeFuture.isDone()) {
throw new ProtocolException("got more than one version ack");
}
- log.debug("{}: Outgoing version handshake complete.", this);
+ if (log.isDebugEnabled())
+ log.debug("{}: Outgoing version handshake complete.", this);
outgoingVersionHandshakeFuture.set(this);
}
private void versionHandshakeComplete() {
- log.debug("{}: Handshake complete.", this);
+ if (log.isDebugEnabled())
+ log.debug("{}: Handshake complete.", this);
setTimeoutEnabled(false);
for (final ListenerRegistration registration : connectedEventListeners) {
registration.executor.execute(new Runnable() {
@@ -640,10 +643,11 @@ protected void processNotFoundMessage(NotFoundMessage m) {
protected void processAlert(AlertMessage m) {
try {
- if (m.isSignatureValid()) {
- log.debug("Received alert from peer {}: {}", this, m.getStatusBar());
- } else {
- log.debug("Received alert with invalid signature from peer {}: {}", this, m.getStatusBar());
+ if (log.isDebugEnabled()) {
+ if (m.isSignatureValid())
+ log.debug("Received alert from peer {}: {}", this, m.getStatusBar());
+ else
+ log.debug("Received alert with invalid signature from peer {}: {}", this, m.getStatusBar());
}
} catch (Throwable t) {
// Signature checking can FAIL on Android platforms before Gingerbread apparently due to bugs in their
@@ -758,7 +762,8 @@ protected void processTransaction(final Transaction tx) throws VerificationExcep
tx.verify();
lock.lock();
try {
- log.debug("{}: Received tx {}", getAddress(), tx.getTxId());
+ if (log.isDebugEnabled())
+ log.debug("{}: Received tx {}", getAddress(), tx.getTxId());
// Label the transaction as coming in from the P2P network (as opposed to being created by us, direct import,
// etc). This helps the wallet decide how to risk analyze it later.
//
@@ -967,18 +972,19 @@ public void onFailure(Throwable throwable) {
}
protected void processBlock(Block m) {
- if (log.isDebugEnabled()) {
+ if (log.isDebugEnabled())
log.debug("{}: Received broadcast block {}", getAddress(), m.getHashAsString());
- }
// Was this block requested by getBlock()?
if (maybeHandleRequestedData(m)) return;
if (blockChain == null) {
- log.debug("Received block but was not configured with an AbstractBlockChain");
+ if (log.isDebugEnabled())
+ log.debug("Received block but was not configured with an AbstractBlockChain");
return;
}
// Did we lose download peer status after requesting block data?
if (!vDownloadData) {
- log.debug("{}: Received block we did not ask for: {}", getAddress(), m.getHashAsString());
+ if (log.isDebugEnabled())
+ log.debug("{}: Received block we did not ask for: {}", getAddress(), m.getHashAsString());
return;
}
pendingBlockDownloads.remove(m.getHash());
@@ -1032,11 +1038,13 @@ protected void endFilteredBlock(FilteredBlock m) {
if (log.isDebugEnabled())
log.debug("{}: Received broadcast filtered block {}", getAddress(), m.getHash().toString());
if (!vDownloadData) {
- log.debug("{}: Received block we did not ask for: {}", getAddress(), m.getHash().toString());
+ if (log.isDebugEnabled())
+ log.debug("{}: Received block we did not ask for: {}", getAddress(), m.getHash().toString());
return;
}
if (blockChain == null) {
- log.debug("Received filtered block but was not configured with an AbstractBlockChain");
+ if (log.isDebugEnabled())
+ log.debug("Received filtered block but was not configured with an AbstractBlockChain");
return;
}
// Note that we currently do nothing about peers which maliciously do not include transactions which
@@ -1220,7 +1228,8 @@ protected void processInv(InventoryMessage inv) {
// We created this transaction ourselves, so don't download.
it.remove();
} else {
- log.debug("{}: getdata on tx {}", getAddress(), item.hash);
+ if (log.isDebugEnabled())
+ log.debug("{}: getdata on tx {}", getAddress(), item.hash);
getdata.addTransaction(item.hash, vPeerVersionMessage.isWitnessSupported());
// Register with the garbage collector that we care about the confidence data for a while.
pendingTxDownloads.add(conf);
@@ -1521,7 +1530,8 @@ public void complete() {
if (!future.isDone()) {
long elapsed = Utils.currentTimeMillis() - startTimeMsec;
Peer.this.addPingTimeData(elapsed);
- log.debug("{}: ping time is {} ms", Peer.this.toString(), elapsed);
+ if (log.isDebugEnabled())
+ log.debug("{}: ping time is {} ms", Peer.this.toString(), elapsed);
future.set(elapsed);
}
}
@@ -1725,7 +1735,7 @@ public void setBloomFilter(BloomFilter filter, boolean andQueryMemPool) {
if (ver == null || !ver.isBloomFilteringSupported())
return;
vBloomFilter = filter;
- log.debug("{}: Sending Bloom filter{}", this, andQueryMemPool ? " and querying mempool" : "");
+ log.info("{}: Sending Bloom filter{}", this, andQueryMemPool ? " and querying mempool" : "");
sendMessage(filter);
if (andQueryMemPool)
sendMessage(new MemoryPoolMessage());
diff --git a/core/src/main/java/org/bitcoinj/core/PeerGroup.java b/core/src/main/java/org/bitcoinj/core/PeerGroup.java
index dad12a8d3de..fd800024ff1 100644
--- a/core/src/main/java/org/bitcoinj/core/PeerGroup.java
+++ b/core/src/main/java/org/bitcoinj/core/PeerGroup.java
@@ -178,34 +178,37 @@ public class PeerGroup implements TransactionBroadcaster {
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
// We received a relevant transaction. We MAY need to recalculate and resend the Bloom filter, but only
- // if we have received a transaction that includes a relevant P2PK output.
+ // if we have received a transaction that includes a relevant P2PK or P2WPKH output.
//
- // The reason is that P2PK outputs, when spent, will not repeat any data we can predict in their
+ // The reason is that P2PK and P2WPKH outputs, when spent, will not repeat any data we can predict in their
// inputs. So a remote peer will update the Bloom filter for us when such an output is seen matching the
- // existing filter, so that it includes the tx hash in which the P2PK output was observed. Thus
+ // existing filter, so that it includes the tx hash in which the P2PK/P2WPKH output was observed. Thus
// the spending transaction will always match (due to the outpoint structure).
//
// Unfortunately, whilst this is required for correct sync of the chain in blocks, there are two edge cases.
//
- // (1) If a wallet receives a relevant, confirmed p2pubkey output that was not broadcast across the network,
+ // (1) If a wallet receives a relevant, confirmed P2PK/P2WPKH output that was not broadcast across the network,
// for example in a coinbase transaction, then the node that's serving us the chain will update its filter
// but the rest will not. If another transaction then spends it, the other nodes won't match/relay it.
//
- // (2) If we receive a p2pubkey output broadcast across the network, all currently connected nodes will see
+ // (2) If we receive a P2PK/P2WPKH output broadcast across the network, all currently connected nodes will see
// it and update their filter themselves, but any newly connected nodes will receive the last filter we
// calculated, which would not include this transaction.
//
- // For this reason we check if the transaction contained any relevant pay to pubkeys and force a recalc
+ // For this reason we check if the transaction contained any relevant P2PKs or P2WPKHs and force a recalc
// and possibly retransmit if so. The recalculation process will end up including the tx hash into the
// filter. In case (1), we need to retransmit the filter to the connected peers. In case (2), we don't
// and shouldn't, we should just recalculate and cache the new filter for next time.
for (TransactionOutput output : tx.getOutputs()) {
- if (ScriptPattern.isP2PK(output.getScriptPubKey()) && output.isMine(wallet)) {
- if (tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
- recalculateFastCatchupAndFilter(FilterRecalculateMode.SEND_IF_CHANGED);
- else
- recalculateFastCatchupAndFilter(FilterRecalculateMode.DONT_SEND);
- return;
+ Script scriptPubKey = output.getScriptPubKey();
+ if (ScriptPattern.isP2PK(scriptPubKey) || ScriptPattern.isP2WPKH(scriptPubKey)) {
+ if (output.isMine(wallet)) {
+ if (tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
+ recalculateFastCatchupAndFilter(FilterRecalculateMode.SEND_IF_CHANGED);
+ else
+ recalculateFastCatchupAndFilter(FilterRecalculateMode.DONT_SEND);
+ return;
+ }
}
}
}
diff --git a/core/src/main/java/org/bitcoinj/core/SegwitAddress.java b/core/src/main/java/org/bitcoinj/core/SegwitAddress.java
index 96de6c567e1..0601e7ded38 100644
--- a/core/src/main/java/org/bitcoinj/core/SegwitAddress.java
+++ b/core/src/main/java/org/bitcoinj/core/SegwitAddress.java
@@ -71,7 +71,7 @@ private SegwitAddress(NetworkParameters params, int witnessVersion, byte[] witne
private static byte[] encode(int witnessVersion, byte[] witnessProgram) throws AddressFormatException {
byte[] convertedProgram = convertBits(witnessProgram, 0, witnessProgram.length, 8, 5, true);
byte[] bytes = new byte[1 + convertedProgram.length];
- bytes[0] = (byte) (Script.encodeToOpN(witnessVersion) & 0xff);
+ bytes[0] = (byte) (witnessVersion & 0xff);
System.arraycopy(convertedProgram, 0, bytes, 1, convertedProgram.length);
return bytes;
}
diff --git a/core/src/main/java/org/bitcoinj/core/Transaction.java b/core/src/main/java/org/bitcoinj/core/Transaction.java
index 50b8abbe395..99d2baa7946 100644
--- a/core/src/main/java/org/bitcoinj/core/Transaction.java
+++ b/core/src/main/java/org/bitcoinj/core/Transaction.java
@@ -927,7 +927,7 @@ public TransactionInput addInput(Sha256Hash spendTxHash, long outputIndex, Scrip
* to understand the values of sigHash and anyoneCanPay: otherwise you can use the other form of this method
* that sets them to typical defaults.
*
- * @throws ScriptException if the scriptPubKey is not a pay to address or pay to pubkey script.
+ * @throws ScriptException if the scriptPubKey is not a pay to address or P2PK script.
*/
public TransactionInput addSignedInput(TransactionOutPoint prevOut, Script scriptPubKey, ECKey sigKey,
SigHash sigHash, boolean anyoneCanPay) throws ScriptException {
@@ -1040,7 +1040,7 @@ public TransactionOutput addOutput(Coin value, Script script) {
*
* @param inputIndex Which input to calculate the signature for, as an index.
* @param key The private key used to calculate the signature.
- * @param redeemScript Byte-exact contents of the scriptPubKey that is being satisified, or the P2SH redeem script.
+ * @param redeemScript Byte-exact contents of the scriptPubKey that is being satisfied, or the P2SH redeem script.
* @param hashType Signing mode, see the enum for documentation.
* @param anyoneCanPay Signing mode, see the SigHash enum for documentation.
* @return A newly calculated signature object that wraps the r, s and sighash components.
@@ -1059,7 +1059,7 @@ public TransactionSignature calculateSignature(int inputIndex, ECKey key,
*
* @param inputIndex Which input to calculate the signature for, as an index.
* @param key The private key used to calculate the signature.
- * @param redeemScript The scriptPubKey that is being satisified, or the P2SH redeem script.
+ * @param redeemScript The scriptPubKey that is being satisfied, or the P2SH redeem script.
* @param hashType Signing mode, see the enum for documentation.
* @param anyoneCanPay Signing mode, see the SigHash enum for documentation.
* @return A newly calculated signature object that wraps the r, s and sighash components.
@@ -1080,7 +1080,7 @@ public TransactionSignature calculateSignature(int inputIndex, ECKey key,
* @param inputIndex Which input to calculate the signature for, as an index.
* @param key The private key used to calculate the signature.
* @param aesKey The AES key to use for decryption of the private key. If null then no decryption is required.
- * @param redeemScript Byte-exact contents of the scriptPubKey that is being satisified, or the P2SH redeem script.
+ * @param redeemScript Byte-exact contents of the scriptPubKey that is being satisfied, or the P2SH redeem script.
* @param hashType Signing mode, see the enum for documentation.
* @param anyoneCanPay Signing mode, see the SigHash enum for documentation.
* @return A newly calculated signature object that wraps the r, s and sighash components.
@@ -1101,7 +1101,7 @@ public TransactionSignature calculateSignature(int inputIndex, ECKey key,
* @param inputIndex Which input to calculate the signature for, as an index.
* @param key The private key used to calculate the signature.
* @param aesKey The AES key to use for decryption of the private key. If null then no decryption is required.
- * @param redeemScript The scriptPubKey that is being satisified, or the P2SH redeem script.
+ * @param redeemScript The scriptPubKey that is being satisfied, or the P2SH redeem script.
* @param hashType Signing mode, see the enum for documentation.
* @param anyoneCanPay Signing mode, see the SigHash enum for documentation.
* @return A newly calculated signature object that wraps the r, s and sighash components.
diff --git a/core/src/main/java/org/bitcoinj/core/Utils.java b/core/src/main/java/org/bitcoinj/core/Utils.java
index c8bfd8f703d..4f387404f18 100644
--- a/core/src/main/java/org/bitcoinj/core/Utils.java
+++ b/core/src/main/java/org/bitcoinj/core/Utils.java
@@ -569,8 +569,8 @@ private enum OS {
private static Runtime runtime = null;
private static OS os = null;
static {
- String runtimeProp = System.getProperty("java.runtime.name").toLowerCase(Locale.US);
- if (runtimeProp == null)
+ String runtimeProp = System.getProperty("java.runtime.name", "").toLowerCase(Locale.US);
+ if (runtimeProp.equals(""))
runtime = null;
else if (runtimeProp.contains("android"))
runtime = Runtime.ANDROID;
@@ -581,8 +581,8 @@ else if (runtimeProp.contains("java(tm) se"))
else
log.info("Unknown java.runtime.name '{}'", runtimeProp);
- String osProp = System.getProperty("os.name").toLowerCase(Locale.US);
- if (osProp == null)
+ String osProp = System.getProperty("os.name", "").toLowerCase(Locale.US);
+ if (osProp.equals(""))
os = null;
else if (osProp.contains("linux"))
os = OS.LINUX;
diff --git a/core/src/main/java/org/bitcoinj/core/VersionMessage.java b/core/src/main/java/org/bitcoinj/core/VersionMessage.java
index 1d9924c1e99..249489c8d56 100644
--- a/core/src/main/java/org/bitcoinj/core/VersionMessage.java
+++ b/core/src/main/java/org/bitcoinj/core/VersionMessage.java
@@ -41,7 +41,7 @@
public class VersionMessage extends Message {
/** The version of this library release, as a string. */
- public static final String BITCOINJ_VERSION = "0.15.2";
+ public static final String BITCOINJ_VERSION = "0.15.5";
/** The value that is prepended to the subVer field of this application. */
public static final String LIBRARY_SUBVER = "/groestlcoinj:" + BITCOINJ_VERSION + "/";
diff --git a/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java b/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java
index 8642759f26d..75b7c2d52ea 100644
--- a/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java
+++ b/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java
@@ -17,8 +17,9 @@
package org.bitcoinj.crypto;
import org.bitcoinj.core.*;
+import org.bouncycastle.crypto.generators.SCrypt;
+
import com.google.common.primitives.Bytes;
-import com.lambdaworks.crypto.SCrypt;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
@@ -133,7 +134,7 @@ public ECKey decrypt(String passphrase) throws BadPassphraseException {
private ECKey decryptNoEC(String normalizedPassphrase) {
try {
- byte[] derived = SCrypt.scrypt(normalizedPassphrase.getBytes(StandardCharsets.UTF_8), addressHash, 16384, 8, 8, 64);
+ byte[] derived = SCrypt.generate(normalizedPassphrase.getBytes(StandardCharsets.UTF_8), addressHash, 16384, 8, 8, 64);
byte[] key = Arrays.copyOfRange(derived, 32, 64);
SecretKeySpec keyspec = new SecretKeySpec(key, "AES");
@@ -155,7 +156,7 @@ private ECKey decryptEC(String normalizedPassphrase) {
byte[] ownerEntropy = Arrays.copyOfRange(content, 0, 8);
byte[] ownerSalt = hasLotAndSequence ? Arrays.copyOfRange(ownerEntropy, 0, 4) : ownerEntropy;
- byte[] passFactorBytes = SCrypt.scrypt(normalizedPassphrase.getBytes(StandardCharsets.UTF_8), ownerSalt, 16384, 8, 8, 32);
+ byte[] passFactorBytes = SCrypt.generate(normalizedPassphrase.getBytes(StandardCharsets.UTF_8), ownerSalt, 16384, 8, 8, 32);
if (hasLotAndSequence) {
byte[] hashBytes = Bytes.concat(passFactorBytes, ownerEntropy);
checkState(hashBytes.length == 40);
@@ -166,7 +167,7 @@ private ECKey decryptEC(String normalizedPassphrase) {
byte[] salt = Bytes.concat(addressHash, ownerEntropy);
checkState(salt.length == 12);
- byte[] derived = SCrypt.scrypt(k.getPubKey(), salt, 1024, 1, 1, 64);
+ byte[] derived = SCrypt.generate(k.getPubKey(), salt, 1024, 1, 1, 64);
byte[] aeskey = Arrays.copyOfRange(derived, 32, 64);
SecretKeySpec keyspec = new SecretKeySpec(aeskey, "AES");
diff --git a/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java b/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java
index cff7e038520..ed236750b7d 100644
--- a/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java
+++ b/core/src/main/java/org/bitcoinj/crypto/KeyCrypterScrypt.java
@@ -20,12 +20,12 @@
import com.google.common.base.Objects;
import com.google.common.base.Stopwatch;
import com.google.protobuf.ByteString;
-import com.lambdaworks.crypto.SCrypt;
import org.bitcoinj.core.Utils;
import org.bitcoinj.wallet.Protos;
import org.bitcoinj.wallet.Protos.ScryptParameters;
import org.bitcoinj.wallet.Protos.Wallet.EncryptionType;
import org.bouncycastle.crypto.engines.AESEngine;
+import org.bouncycastle.crypto.generators.SCrypt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.bouncycastle.crypto.BufferedBlockCipher;
@@ -157,9 +157,9 @@ public KeyParameter deriveKey(CharSequence password) throws KeyCrypterException
}
final Stopwatch watch = Stopwatch.createStarted();
- byte[] keyBytes = SCrypt.scrypt(passwordBytes, salt, (int) scryptParameters.getN(), scryptParameters.getR(), scryptParameters.getP(), KEY_LENGTH);
+ byte[] keyBytes = SCrypt.generate(passwordBytes, salt, (int) scryptParameters.getN(), scryptParameters.getR(), scryptParameters.getP(), KEY_LENGTH);
watch.stop();
- log.info("Deriving key took {} for {} scrypt iterations.", watch, scryptParameters.getN());
+ log.info("Deriving key took {} for {}.", watch, scryptParametersString());
return new KeyParameter(keyBytes);
} catch (Exception e) {
throw new KeyCrypterException("Could not generate key from password and salt.", e);
@@ -264,7 +264,11 @@ public EncryptionType getUnderstoodEncryptionType() {
@Override
public String toString() {
- return "AES-" + KEY_LENGTH * 8 + "-CBC, Scrypt (N: " + scryptParameters.getN() + ")";
+ return "AES-" + KEY_LENGTH * 8 + "-CBC, Scrypt (" + scryptParametersString() + ")";
+ }
+
+ private String scryptParametersString() {
+ return "N=" + scryptParameters.getN() + ", r=" + scryptParameters.getR() + ", p=" + scryptParameters.getP();
}
@Override
diff --git a/core/src/main/java/org/bitcoinj/script/Script.java b/core/src/main/java/org/bitcoinj/script/Script.java
index fab1d66a5da..843fffa35ea 100644
--- a/core/src/main/java/org/bitcoinj/script/Script.java
+++ b/core/src/main/java/org/bitcoinj/script/Script.java
@@ -189,7 +189,7 @@ public List getChunks() {
*
* The reason for this split, instead of just interpreting directly, is to make it easier
* to reach into a programs structure and pull out bits of data without having to run it.
- * This is necessary to render the to/from addresses of transactions in a user interface.
+ * This is necessary to render the to addresses of transactions in a user interface.
* Bitcoin Core does something similar.
*/
private void parse(byte[] program) throws ScriptException {
diff --git a/core/src/main/java/org/bitcoinj/script/ScriptChunk.java b/core/src/main/java/org/bitcoinj/script/ScriptChunk.java
index a8b2d29830d..fc54d4d5c64 100644
--- a/core/src/main/java/org/bitcoinj/script/ScriptChunk.java
+++ b/core/src/main/java/org/bitcoinj/script/ScriptChunk.java
@@ -44,11 +44,11 @@ public class ScriptChunk {
public final byte[] data;
private int startLocationInProgram;
- public ScriptChunk(int opcode, byte[] data) {
+ public ScriptChunk(int opcode, @Nullable byte[] data) {
this(opcode, data, -1);
}
- public ScriptChunk(int opcode, byte[] data, int startLocationInProgram) {
+ public ScriptChunk(int opcode, @Nullable byte[] data, int startLocationInProgram) {
this.opcode = opcode;
this.data = data;
this.startLocationInProgram = startLocationInProgram;
diff --git a/core/src/main/java/org/bitcoinj/script/ScriptPattern.java b/core/src/main/java/org/bitcoinj/script/ScriptPattern.java
index ff282e427fa..3f6321e51a6 100644
--- a/core/src/main/java/org/bitcoinj/script/ScriptPattern.java
+++ b/core/src/main/java/org/bitcoinj/script/ScriptPattern.java
@@ -197,8 +197,8 @@ public static byte[] extractHashFromP2WH(Script script) {
}
/**
- * Returns whether this script matches the format used for multisig outputs:
- * {@code [n] [keys...] [m] CHECKMULTISIG}
+ * Returns whether this script matches the format used for m-of-n multisig outputs:
+ * {@code [m] [keys...] [n] CHECKMULTISIG}
*/
public static boolean isSentToMultisig(Script script) {
List chunks = script.chunks;
diff --git a/core/src/main/java/org/bitcoinj/wallet/Wallet.java b/core/src/main/java/org/bitcoinj/wallet/Wallet.java
index b31f6e3be07..6088ff50ea9 100644
--- a/core/src/main/java/org/bitcoinj/wallet/Wallet.java
+++ b/core/src/main/java/org/bitcoinj/wallet/Wallet.java
@@ -2609,9 +2609,17 @@ private void maybeMovePool(Transaction tx, String context) {
}
/**
- * Calls {@link Wallet#commitTx} if tx is not already in the pending pool
+ * Updates the wallet with the given transaction: puts it into the pending pool, sets the spent flags and runs
+ * the onCoinsSent/onCoinsReceived event listener.
+ *
+ * Triggers an auto save (if enabled.)
+ *
+ * Unlike {@link Wallet#commitTx} this method does not throw an exception if the transaction
+ * was already added to the wallet, instead it will return {@code false}
*
+ * @param tx transaction to commit
* @return true if the tx was added to the wallet, or false if it was already in the pending pool
+ * @throws VerificationException If transaction fails to verify
*/
public boolean maybeCommitTx(Transaction tx) throws VerificationException {
tx.verify();
@@ -2699,15 +2707,21 @@ public boolean maybeCommitTx(Transaction tx) throws VerificationException {
}
/**
- *
Updates the wallet with the given transaction: puts it into the pending pool, sets the spent flags and runs
- * the onCoinsSent/onCoinsReceived event listener. Used in two situations:
- *
+ * Updates the wallet with the given transaction: puts it into the pending pool, sets the spent flags and runs
+ * the onCoinsSent/onCoinsReceived event listener. Used in two situations:
+ *
*
* - When we have just successfully transmitted the tx we created to the network.
* - When we receive a pending transaction that didn't appear in the chain yet, and we did not create it.
*
+ *
+ * Triggers an auto save (if enabled.)
+ *
+ * Unlike {@link Wallet#maybeCommitTx} {@code commitTx} throws an exception if the transaction
+ * was already added to the wallet.
*
- *
Triggers an auto save.
+ * @param tx transaction to commit
+ * @throws VerificationException if transaction was already in the pending pool
*/
public void commitTx(Transaction tx) throws VerificationException {
checkArgument(maybeCommitTx(tx), "commitTx called on the same transaction twice");
diff --git a/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java b/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java
index 2b8539c632f..b69dcd52d9f 100644
--- a/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java
+++ b/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java
@@ -607,8 +607,8 @@ public void shutdown() {
}
@Test
- public void testBloomOnP2Pubkey() throws Exception {
- // Cover bug 513. When a relevant transaction with a p2pubkey output is found, the Bloom filter should be
+ public void testBloomOnP2PK() throws Exception {
+ // Cover bug 513. When a relevant transaction with a P2PK output is found, the Bloom filter should be
// recalculated to include that transaction hash but not re-broadcast as the remote nodes should have followed
// the same procedure. However a new node that's connected should get the fresh filter.
peerGroup.start();
@@ -616,12 +616,13 @@ public void testBloomOnP2Pubkey() throws Exception {
// Create a couple of peers.
InboundMessageQueuer p1 = connectPeer(1);
InboundMessageQueuer p2 = connectPeer(2);
- // Create a pay to pubkey tx.
+ // Create a P2PK tx.
Transaction tx = FakeTxBuilder.createFakeTx(UNITTEST, COIN, key);
Transaction tx2 = new Transaction(UNITTEST);
tx2.addInput(tx.getOutput(0));
TransactionOutPoint outpoint = tx2.getInput(0).getOutpoint();
assertTrue(p1.lastReceivedFilter.contains(key.getPubKey()));
+ assertTrue(p1.lastReceivedFilter.contains(key.getPubKeyHash()));
assertFalse(p1.lastReceivedFilter.contains(tx.getTxId().getBytes()));
inbound(p1, tx);
// p1 requests dep resolution, p2 is quiet.
@@ -635,6 +636,7 @@ public void testBloomOnP2Pubkey() throws Exception {
// Now we connect p3 and there is a new bloom filter sent, that DOES match the relevant outpoint.
InboundMessageQueuer p3 = connectPeer(3);
assertTrue(p3.lastReceivedFilter.contains(key.getPubKey()));
+ assertTrue(p3.lastReceivedFilter.contains(key.getPubKeyHash()));
assertTrue(p3.lastReceivedFilter.contains(outpoint.unsafeBitcoinSerialize()));
}
diff --git a/core/src/test/java/org/bitcoinj/script/ScriptTest.java b/core/src/test/java/org/bitcoinj/script/ScriptTest.java
index 8777f0b37c7..587557203e5 100644
--- a/core/src/test/java/org/bitcoinj/script/ScriptTest.java
+++ b/core/src/test/java/org/bitcoinj/script/ScriptTest.java
@@ -437,7 +437,7 @@ public void testCLTVPaymentChannelOutput() {
@Test
public void getToAddress() throws Exception {
- // pay to pubkey
+ // P2PK
ECKey toKey = new ECKey();
Address toAddress = LegacyAddress.fromKey(TESTNET, toKey);
assertEquals(toAddress, ScriptBuilder.createP2PKOutputScript(toKey).getToAddress(TESTNET, true));
diff --git a/core/src/test/java/org/bitcoinj/wallet/DefaultRiskAnalysisTest.java b/core/src/test/java/org/bitcoinj/wallet/DefaultRiskAnalysisTest.java
index d731352fd1a..5a146d4e251 100644
--- a/core/src/test/java/org/bitcoinj/wallet/DefaultRiskAnalysisTest.java
+++ b/core/src/test/java/org/bitcoinj/wallet/DefaultRiskAnalysisTest.java
@@ -209,7 +209,7 @@ public void standardOutputs() throws Exception {
tx.addInput(MAINNET.getGenesisBlock().getTransactions().get(0).getOutput(0));
// A pay to address output
tx.addOutput(Coin.CENT, ScriptBuilder.createP2PKHOutputScript(key1));
- // A pay to pubkey output
+ // A P2PK output
tx.addOutput(Coin.CENT, ScriptBuilder.createP2PKOutputScript(key1));
tx.addOutput(Coin.CENT, ScriptBuilder.createP2PKOutputScript(key1));
// 1-of-2 multisig output.
diff --git a/examples/build.gradle b/examples/build.gradle
index 5c1b1a0df96..2134d7be043 100644
--- a/examples/build.gradle
+++ b/examples/build.gradle
@@ -5,12 +5,13 @@ eclipse.project.name = 'bitcoinj-examples'
dependencies {
implementation project(':core')
- implementation 'com.google.guava:guava:27.0.1-android'
+ implementation 'com.google.guava:guava:27.1-android'
implementation 'net.sf.jopt-simple:jopt-simple:5.0.4'
- implementation 'org.slf4j:slf4j-jdk14:1.7.25'
+ implementation 'org.slf4j:slf4j-jdk14:1.7.28'
implementation 'org.fusesource.leveldbjni:leveldbjni-all:1.8'
}
sourceCompatibility = 1.8
compileJava.options.encoding = 'UTF-8'
compileTestJava.options.encoding = 'UTF-8'
+javadoc.options.encoding = 'UTF-8'
diff --git a/tools/build.gradle b/tools/build.gradle
index 9a78bfde62c..476b4ecb013 100644
--- a/tools/build.gradle
+++ b/tools/build.gradle
@@ -5,14 +5,15 @@ eclipse.project.name = 'bitcoinj-tools'
dependencies {
implementation project(':core')
- implementation 'com.google.guava:guava:27.0.1-android'
+ implementation 'com.google.guava:guava:27.1-android'
implementation 'net.sf.jopt-simple:jopt-simple:5.0.4'
- implementation 'org.slf4j:slf4j-jdk14:1.7.25'
+ implementation 'org.slf4j:slf4j-jdk14:1.7.28'
}
sourceCompatibility = 1.8
compileJava.options.encoding = 'UTF-8'
compileTestJava.options.encoding = 'UTF-8'
+javadoc.options.encoding = 'UTF-8'
task wallet_tool(type: JavaExec) {
description = 'Print and manipulate wallets.'
diff --git a/wallettemplate/build.gradle b/wallettemplate/build.gradle
index 9e0fe15d27a..918bc208300 100644
--- a/wallettemplate/build.gradle
+++ b/wallettemplate/build.gradle
@@ -11,11 +11,11 @@ eclipse.project.name = 'bitcoinj-wallettemplate'
dependencies {
implementation project(':core')
- implementation 'com.google.guava:guava:27.0.1-android'
+ implementation 'com.google.guava:guava:27.1-android'
implementation 'org.fxmisc.easybind:easybind:1.0.2'
implementation 'de.jensd:fontawesomefx:8.0.0'
implementation 'net.glxn:qrgen:1.3'
- implementation 'org.slf4j:slf4j-jdk14:1.7.25'
+ implementation 'org.slf4j:slf4j-jdk14:1.7.28'
}
javafx {
@@ -25,6 +25,7 @@ javafx {
sourceCompatibility = 1.11
compileJava.options.encoding = 'UTF-8'
compileTestJava.options.encoding = 'UTF-8'
+javadoc.options.encoding = 'UTF-8'
mainClassName = 'wallettemplate.Main'