diff --git a/core/src/main/java/org/bitcoinj/core/PeerAddress.java b/core/src/main/java/org/bitcoinj/core/PeerAddress.java index 825ddb3b355..8adfede0991 100644 --- a/core/src/main/java/org/bitcoinj/core/PeerAddress.java +++ b/core/src/main/java/org/bitcoinj/core/PeerAddress.java @@ -46,7 +46,7 @@ * A PeerAddress holds an IP address and port number representing the network location of * a peer in the Bitcoin P2P network. It exists primarily for serialization purposes. *

- * Instances of this class are not safe for use by multiple threads. + * This class is immutable and thread-safe. */ public class PeerAddress { @Nullable diff --git a/core/src/main/java/org/bitcoinj/core/Transaction.java b/core/src/main/java/org/bitcoinj/core/Transaction.java index 1705f7d0cbb..cf48b06b647 100644 --- a/core/src/main/java/org/bitcoinj/core/Transaction.java +++ b/core/src/main/java/org/bitcoinj/core/Transaction.java @@ -18,7 +18,6 @@ package org.bitcoinj.core; import com.google.common.base.MoreObjects; -import com.google.common.math.IntMath; import org.bitcoinj.base.Address; import org.bitcoinj.base.Coin; import org.bitcoinj.base.Network; @@ -151,6 +150,22 @@ private static int sortableBlockHeight(Transaction tx) { */ public static final Coin DEFAULT_TX_FEE = Coin.valueOf(100_000); // 1 mBTC + /** + * The scale factor for Witness data in Segregated Witness transactions. + * @see BIP 141 + */ + public static final int WITNESS_SCALE_FACTOR = 4; + + /** + * Virtual transaction size is defined as Transaction weight / 4 (rounded up to the next integer). + * @param weight the transaction weight + * @return the virtual transaction size + * @see BIP 141 + */ + public static int calculateVirtualTransactionSize(int weight) { + return (weight + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; // round up + } + private final int protocolVersion; // These are bitcoin serialized. @@ -397,7 +412,7 @@ public int getWeight() { public int getVsize() { if (!hasWitnesses()) return this.messageSize(); - return IntMath.divide(getWeight(), 4, RoundingMode.CEILING); // round up + return calculateVirtualTransactionSize(getWeight()); } diff --git a/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java b/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java index 358900b8d17..15400bc30a2 100644 --- a/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java +++ b/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java @@ -18,7 +18,6 @@ package org.bitcoinj.core; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Iterators; import org.bitcoinj.base.Sha256Hash; import org.bitcoinj.base.internal.TimeUtils; import org.bitcoinj.utils.ListenerRegistration; @@ -328,9 +327,7 @@ public int numBroadcastPeers() { * Returns a snapshot of {@link PeerAddress}es that announced the transaction. */ public Set getBroadcastBy() { - Set broadcastBySet = new HashSet<>(); - Iterators.addAll(broadcastBySet, broadcastBy.listIterator()); - return broadcastBySet; + return Collections.unmodifiableSet(new HashSet<>(broadcastBy)); } /** Returns true if the given address has been seen via markBroadcastBy() */ diff --git a/core/src/main/java/org/bitcoinj/crypto/DeterministicKey.java b/core/src/main/java/org/bitcoinj/crypto/DeterministicKey.java index 1f7345beb09..6ba81818c0f 100644 --- a/core/src/main/java/org/bitcoinj/crypto/DeterministicKey.java +++ b/core/src/main/java/org/bitcoinj/crypto/DeterministicKey.java @@ -720,17 +720,6 @@ public void clearCreationTime() { super.clearCreationTime(); } - /** @deprecated use {@link #setCreationTime(Instant)} */ - @Deprecated - public void setCreationTimeSeconds(long creationTimeSecs) { - if (creationTimeSecs > 0) - setCreationTime(Instant.ofEpochSecond(creationTimeSecs)); - else if (creationTimeSecs == 0) - clearCreationTime(); - else - throw new IllegalArgumentException("Cannot set creation time to negative value: " + creationTimeSecs); - } - /** * Verifies equality of all fields but NOT the parent pointer (thus the same key derived in two separate hierarchy * objects will equal each other. diff --git a/core/src/main/java/org/bitcoinj/crypto/ECKey.java b/core/src/main/java/org/bitcoinj/crypto/ECKey.java index d13a6b7e16a..b35fa65cca8 100644 --- a/core/src/main/java/org/bitcoinj/crypto/ECKey.java +++ b/core/src/main/java/org/bitcoinj/crypto/ECKey.java @@ -1130,17 +1130,6 @@ public void clearCreationTime() { this.creationTime = null; } - /** @deprecated use {@link #setCreationTime(Instant)} */ - @Deprecated - public void setCreationTimeSeconds(long creationTimeSecs) { - if (creationTimeSecs > 0) - setCreationTime(Instant.ofEpochSecond(creationTimeSecs)); - else if (creationTimeSecs == 0) - clearCreationTime(); - else - throw new IllegalArgumentException("Cannot set creation time to negative value: " + creationTimeSecs); - } - /** * Create an encrypted private key with the keyCrypter and the AES key supplied. * This method returns a new encrypted key and leaves the original unchanged. diff --git a/core/src/main/java/org/bitcoinj/wallet/Wallet.java b/core/src/main/java/org/bitcoinj/wallet/Wallet.java index 8796c34fc65..55b25a2e07b 100644 --- a/core/src/main/java/org/bitcoinj/wallet/Wallet.java +++ b/core/src/main/java/org/bitcoinj/wallet/Wallet.java @@ -19,7 +19,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ArrayListMultimap; -import com.google.common.math.IntMath; import com.google.protobuf.ByteString; import org.bitcoinj.core.internal.GuardedBy; import org.bitcoinj.base.BitcoinNetwork; @@ -5367,8 +5366,7 @@ private int estimateVirtualBytesForSigning(Script script) { } else if (ScriptPattern.isP2WPKH(script)) { ECKey key = findKeyFromPubKeyHash(ScriptPattern.extractHashFromP2WH(script), ScriptType.P2WPKH); Objects.requireNonNull(key, "Coin selection includes unspendable outputs"); - return IntMath.divide(script.getNumberOfBytesRequiredToSpend(key, null), 4, - RoundingMode.CEILING); // round up + return Transaction.calculateVirtualTransactionSize(script.getNumberOfBytesRequiredToSpend(key, null)); } else if (ScriptPattern.isP2SH(script)) { Script redeemScript = findRedeemDataFromScriptHash(ScriptPattern.extractHashFromP2SH(script)).redeemScript; Objects.requireNonNull(redeemScript, "Coin selection includes unspendable outputs"); diff --git a/core/src/test/java/org/bitcoinj/core/BitcoinSerializerTest.java b/core/src/test/java/org/bitcoinj/core/BitcoinSerializerTest.java index e8ccaafe263..c3e83a7d5cd 100644 --- a/core/src/test/java/org/bitcoinj/core/BitcoinSerializerTest.java +++ b/core/src/test/java/org/bitcoinj/core/BitcoinSerializerTest.java @@ -17,7 +17,6 @@ package org.bitcoinj.core; -import com.google.common.io.BaseEncoding; import org.bitcoinj.base.internal.ByteUtils; import org.bitcoinj.base.internal.TimeUtils; import org.bitcoinj.params.MainNetParams; @@ -40,12 +39,11 @@ import static org.junit.Assert.assertTrue; public class BitcoinSerializerTest { - private static final BaseEncoding HEX = BaseEncoding.base16().lowerCase(); private static final NetworkParameters MAINNET = MainNetParams.get(); private static final byte[] ADDRESS_MESSAGE_BYTES = ByteUtils.parseHex("f9beb4d96164647200000000000000001f000000" + "ed52399b01e215104d010000000000000000000000000000000000ffff0a000001208d"); - private static final byte[] TRANSACTION_MESSAGE_BYTES = HEX.withSeparator(" ", 2).decode( + private static final byte[] TRANSACTION_MESSAGE_BYTES = ByteUtils.parseHex(( "f9 be b4 d9 74 78 00 00 00 00 00 00 00 00 00 00" + "02 01 00 00 e2 93 cd be 01 00 00 00 01 6d bd db" + "08 5b 1d 8a f7 51 84 f0 bc 01 fa d5 8d 12 66 e9" + @@ -63,7 +61,7 @@ public class BitcoinSerializerTest { "cd 1c be a6 e7 45 8a 7a ba d5 12 a9 d9 ea 1a fb" + "22 5e 88 ac 80 fa e9 c7 00 00 00 00 19 76 a9 14" + "0e ab 5b ea 43 6a 04 84 cf ab 12 48 5e fd a0 b7" + - "8b 4e cc 52 88 ac 00 00 00 00"); + "8b 4e cc 52 88 ac 00 00 00 00").replaceAll("\\s", "")); @Test public void testAddr() throws Exception { diff --git a/core/src/test/java/org/bitcoinj/core/SendHeadersMessageTest.java b/core/src/test/java/org/bitcoinj/core/SendHeadersMessageTest.java index eafac639de0..e7cba189735 100644 --- a/core/src/test/java/org/bitcoinj/core/SendHeadersMessageTest.java +++ b/core/src/test/java/org/bitcoinj/core/SendHeadersMessageTest.java @@ -16,8 +16,8 @@ package org.bitcoinj.core; -import com.google.common.io.BaseEncoding; import org.bitcoinj.base.BitcoinNetwork; +import org.bitcoinj.base.internal.ByteUtils; import org.junit.Test; import java.nio.ByteBuffer; @@ -25,12 +25,11 @@ import static org.junit.Assert.assertTrue; public class SendHeadersMessageTest { - private static final BaseEncoding HEX = BaseEncoding.base16().lowerCase(); @Test public void decodeAndEncode() throws Exception { - byte[] message = HEX - .decode("00000000fabfb5da73656e646865616465727300000000005df6e0e2fabfb5da70696e670000000000000000080000009a" + byte[] message = ByteUtils.parseHex( + "00000000fabfb5da73656e646865616465727300000000005df6e0e2fabfb5da70696e670000000000000000080000009a" + "65b9cc9840c9729e4502b200000000000000000000000000000d000000000000000000000000000000000000000000000000007ad82" + "872c28ac782102f5361746f7368693a302e31342e312fe41d000001fabfb5da76657261636b000000000000000000005df6e0e2fabf" + "b5da616c65727400000000000000a80000001bf9aaea60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01fff" diff --git a/core/src/test/java/org/bitcoinj/wallet/BasicKeyChainTest.java b/core/src/test/java/org/bitcoinj/wallet/BasicKeyChainTest.java index fb1cac93927..507c41e0b9e 100644 --- a/core/src/test/java/org/bitcoinj/wallet/BasicKeyChainTest.java +++ b/core/src/test/java/org/bitcoinj/wallet/BasicKeyChainTest.java @@ -32,7 +32,6 @@ import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -74,7 +73,7 @@ public void importKeys() { final ECKey key1 = ECKey.random(); TimeUtils.rollMockClock(Duration.ofDays(1)); final ECKey key2 = ECKey.random(); - final ArrayList keys = Lists.newArrayList(key1, key2); + final List keys = Lists.newArrayList(key1, key2); // Import two keys, check the event is correct. assertEquals(2, chain.importKeys(keys)); @@ -84,11 +83,11 @@ public void importKeys() { assertEquals(now, chain.earliestKeyCreationTime()); // Check we ignore duplicates. final ECKey newKey = ECKey.random(); - keys.add(newKey); - assertEquals(1, chain.importKeys(keys)); + final List keys2 = Lists.newArrayList(key1, key2, newKey); + assertEquals(1, chain.importKeys(keys2)); assertTrue(onKeysAddedRan.getAndSet(false)); assertEquals(newKey, onKeysAdded.getAndSet(null).get(0)); - assertEquals(0, chain.importKeys(keys)); + assertEquals(0, chain.importKeys(keys2)); assertFalse(onKeysAddedRan.getAndSet(false)); assertNull(onKeysAdded.get()); @@ -126,14 +125,14 @@ public void checkPasswordNoKeys() { @Test(expected = IllegalStateException.class) public void checkPasswordNotEncrypted() { - final ArrayList keys = Lists.newArrayList(ECKey.random(), ECKey.random()); + final List keys = Lists.newArrayList(ECKey.random(), ECKey.random()); chain.importKeys(keys); chain.checkPassword("test"); } @Test(expected = IllegalStateException.class) public void doubleEncryptFails() { - final ArrayList keys = Lists.newArrayList(ECKey.random(), ECKey.random()); + final List keys = Lists.newArrayList(ECKey.random(), ECKey.random()); chain.importKeys(keys); chain = chain.toEncrypted("foo"); chain.toEncrypted("foo");