mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-01-18 21:32:35 +01:00
TransactionOutPoint: divorce from Message
It is never sent on its own, so it doesn't need to be a `Message`. * A static constructur `read()` replaces the native constructor that deserialized from a payload. * A `write()` helper replace `bitcoinSerializeToStream()`. * A `serialize()` helper replace `bitcoinSerialize()`. * A `BYTES` constant replaces `getMessageSize()`. This comes with a test.
This commit is contained in:
parent
4248804f82
commit
fbc5185b5a
@ -257,7 +257,7 @@ public class BloomFilter extends Message {
|
||||
|
||||
/** Inserts the given transaction outpoint. */
|
||||
public synchronized void insert(TransactionOutPoint outpoint) {
|
||||
insert(outpoint.bitcoinSerialize());
|
||||
insert(outpoint.serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -359,7 +359,7 @@ public class BloomFilter extends Message {
|
||||
}
|
||||
if (found) return true;
|
||||
for (TransactionInput input : tx.getInputs()) {
|
||||
if (contains(input.getOutpoint().bitcoinSerialize())) {
|
||||
if (contains(input.getOutpoint().serialize())) {
|
||||
return true;
|
||||
}
|
||||
for (ScriptChunk chunk : input.getScriptSig().getChunks()) {
|
||||
|
@ -682,7 +682,7 @@ public class Transaction extends Message {
|
||||
TransactionInput input = new TransactionInput(this, payload.slice());
|
||||
inputs.add(input);
|
||||
// intentionally read again, due to the slice above
|
||||
Buffers.skipBytes(payload, TransactionOutPoint.MESSAGE_LENGTH);
|
||||
Buffers.skipBytes(payload, TransactionOutPoint.BYTES);
|
||||
VarInt scriptLenVarInt = VarInt.read(payload);
|
||||
int scriptLen = scriptLenVarInt.intValue();
|
||||
Buffers.skipBytes(payload, scriptLen + 4);
|
||||
|
@ -159,14 +159,14 @@ public class TransactionInput extends Message {
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||
outpoint = new TransactionOutPoint(payload);
|
||||
outpoint = TransactionOutPoint.read(payload);
|
||||
scriptBytes = Buffers.readLengthPrefixedBytes(payload);
|
||||
sequence = ByteUtils.readUint32(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageSize() {
|
||||
int size = outpoint.getMessageSize();
|
||||
int size = TransactionOutPoint.BYTES;
|
||||
size += VarInt.sizeOf(scriptBytes.length) + scriptBytes.length;
|
||||
size += 4; // sequence
|
||||
return size;
|
||||
@ -174,7 +174,7 @@ public class TransactionInput extends Message {
|
||||
|
||||
@Override
|
||||
protected void bitcoinSerializeToStream(OutputStream stream) throws IOException {
|
||||
outpoint.bitcoinSerializeToStream(stream);
|
||||
stream.write(outpoint.serialize());
|
||||
stream.write(VarInt.of(scriptBytes.length).serialize());
|
||||
stream.write(scriptBytes);
|
||||
ByteUtils.writeInt32LE(sequence, stream);
|
||||
|
@ -29,8 +29,8 @@ import org.bitcoinj.wallet.KeyBag;
|
||||
import org.bitcoinj.wallet.RedeemData;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Objects;
|
||||
@ -43,9 +43,8 @@ import static org.bitcoinj.base.internal.Preconditions.checkState;
|
||||
*
|
||||
* <p>Instances of this class are not safe for use by multiple threads.</p>
|
||||
*/
|
||||
public class TransactionOutPoint extends Message {
|
||||
|
||||
static final int MESSAGE_LENGTH = 36;
|
||||
public class TransactionOutPoint {
|
||||
public static final int BYTES = 36;
|
||||
|
||||
/** Special outpoint that normally marks a coinbase input. It's also used as a test dummy. */
|
||||
public static final TransactionOutPoint UNCONNECTED =
|
||||
@ -62,6 +61,19 @@ public class TransactionOutPoint extends Message {
|
||||
// The connected output.
|
||||
TransactionOutput connectedOutput;
|
||||
|
||||
/**
|
||||
* Deserialize this transaction outpoint from a given payload.
|
||||
*
|
||||
* @param payload payload to deserialize from
|
||||
* @return read transaction outpoint
|
||||
* @throws BufferUnderflowException if the read message extends beyond the remaining bytes of the payload
|
||||
*/
|
||||
public static TransactionOutPoint read(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||
Sha256Hash hash = Sha256Hash.read(payload);
|
||||
long index = ByteUtils.readUint32(payload);
|
||||
return new TransactionOutPoint(index, hash);
|
||||
}
|
||||
|
||||
public TransactionOutPoint(long index, Transaction fromTx) {
|
||||
super();
|
||||
checkArgument(index >= 0 && index <= ByteUtils.MAX_UNSIGNED_INTEGER, () ->
|
||||
@ -85,28 +97,37 @@ public class TransactionOutPoint extends Message {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the message. This is usually part of a transaction message.
|
||||
* @throws ProtocolException
|
||||
* Write this transaction outpoint into the given buffer.
|
||||
*
|
||||
* @param buf buffer to write into
|
||||
* @return the buffer
|
||||
* @throws BufferOverflowException if the outpoint doesn't fit the remaining buffer
|
||||
*/
|
||||
public TransactionOutPoint(ByteBuffer payload) throws ProtocolException {
|
||||
super(payload);
|
||||
public ByteBuffer write(ByteBuffer buf) throws BufferOverflowException {
|
||||
buf.put(hash.serialize());
|
||||
ByteUtils.writeInt32LE(index, buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||
hash = Sha256Hash.read(payload);
|
||||
index = ByteUtils.readUint32(payload);
|
||||
/**
|
||||
* Allocates a byte array and writes this transaction outpoint into it.
|
||||
*
|
||||
* @return byte array containing the transaction outpoint
|
||||
*/
|
||||
public byte[] serialize() {
|
||||
return write(ByteBuffer.allocate(BYTES)).array();
|
||||
}
|
||||
|
||||
@Override
|
||||
/** @deprecated use {@link #serialize()} */
|
||||
@Deprecated
|
||||
public byte[] bitcoinSerialize() {
|
||||
return serialize();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #BYTES} */
|
||||
@Deprecated
|
||||
public int getMessageSize() {
|
||||
return MESSAGE_LENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bitcoinSerializeToStream(OutputStream stream) throws IOException {
|
||||
stream.write(hash.serialize());
|
||||
ByteUtils.writeInt32LE(index, stream);
|
||||
return BYTES;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright by the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.bitcoinj.core;
|
||||
|
||||
import junitparams.JUnitParamsRunner;
|
||||
import junitparams.Parameters;
|
||||
import org.bitcoinj.base.Sha256Hash;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
@RunWith(JUnitParamsRunner.class)
|
||||
public class TransactionOutPointTest {
|
||||
@Test
|
||||
@Parameters(method = "randomOutPoints")
|
||||
public void readAndWrite(TransactionOutPoint outpoint) {
|
||||
ByteBuffer buf = ByteBuffer.allocate(TransactionOutPoint.BYTES);
|
||||
outpoint.write(buf);
|
||||
assertFalse(buf.hasRemaining());
|
||||
((Buffer) buf).rewind();
|
||||
TransactionOutPoint outpointCopy = TransactionOutPoint.read(buf);
|
||||
assertFalse(buf.hasRemaining());
|
||||
assertEquals(outpoint, outpointCopy);
|
||||
}
|
||||
|
||||
private Iterator<TransactionOutPoint> randomOutPoints() {
|
||||
Random random = new Random();
|
||||
return Stream.generate(() -> {
|
||||
byte[] randomBytes = new byte[Sha256Hash.LENGTH];
|
||||
random.nextBytes(randomBytes);
|
||||
return new TransactionOutPoint(Integer.toUnsignedLong(random.nextInt()), Sha256Hash.wrap(randomBytes));
|
||||
}).limit(10).iterator();
|
||||
}
|
||||
}
|
@ -1680,10 +1680,10 @@ public class WalletTest extends TestWithWallet {
|
||||
wallet.addWatchedAddress(watchedAddress);
|
||||
|
||||
// Note that this has a 1e-12 chance of failing this unit test due to a false positive
|
||||
assertFalse(wallet.getBloomFilter(1e-12).contains(outPoint.bitcoinSerialize()));
|
||||
assertFalse(wallet.getBloomFilter(1e-12).contains(outPoint.serialize()));
|
||||
|
||||
sendMoneyToWallet(BlockChain.NewBlockType.BEST_CHAIN, t1);
|
||||
assertTrue(wallet.getBloomFilter(1e-12).contains(outPoint.bitcoinSerialize()));
|
||||
assertTrue(wallet.getBloomFilter(1e-12).contains(outPoint.serialize()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1733,10 +1733,10 @@ public class WalletTest extends TestWithWallet {
|
||||
TransactionOutPoint outPoint = new TransactionOutPoint(0, t1);
|
||||
|
||||
// Note that this has a 1e-12 chance of failing this unit test due to a false positive
|
||||
assertFalse(wallet.getBloomFilter(1e-12).contains(outPoint.bitcoinSerialize()));
|
||||
assertFalse(wallet.getBloomFilter(1e-12).contains(outPoint.serialize()));
|
||||
|
||||
sendMoneyToWallet(BlockChain.NewBlockType.BEST_CHAIN, t1);
|
||||
assertFalse(wallet.getBloomFilter(1e-12).contains(outPoint.bitcoinSerialize()));
|
||||
assertFalse(wallet.getBloomFilter(1e-12).contains(outPoint.serialize()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1751,10 +1751,10 @@ public class WalletTest extends TestWithWallet {
|
||||
Transaction t1 = createFakeTx(TESTNET, CENT, address);
|
||||
TransactionOutPoint outPoint = new TransactionOutPoint(0, t1);
|
||||
|
||||
assertFalse(wallet.getBloomFilter(falsePositiveRate).contains(outPoint.bitcoinSerialize()));
|
||||
assertFalse(wallet.getBloomFilter(falsePositiveRate).contains(outPoint.serialize()));
|
||||
|
||||
sendMoneyToWallet(BlockChain.NewBlockType.BEST_CHAIN, t1);
|
||||
assertTrue(wallet.getBloomFilter(falsePositiveRate).contains(outPoint.bitcoinSerialize()));
|
||||
assertTrue(wallet.getBloomFilter(falsePositiveRate).contains(outPoint.serialize()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -653,7 +653,7 @@ public class PeerGroupTest extends TestWithPeerGroup {
|
||||
InboundMessageQueuer p3 = connectPeer(3);
|
||||
assertTrue(p3.lastReceivedFilter.contains(key.getPubKey()));
|
||||
assertTrue(p3.lastReceivedFilter.contains(key.getPubKeyHash()));
|
||||
assertTrue(p3.lastReceivedFilter.contains(outpoint.bitcoinSerialize()));
|
||||
assertTrue(p3.lastReceivedFilter.contains(outpoint.serialize()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user