Revert "Fix parsertest"

This commit is contained in:
Manfred Karrer 2018-03-09 14:42:56 -05:00 committed by GitHub
parent 182158af20
commit 456fd28e94
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 232 additions and 398 deletions

View file

@ -18,7 +18,7 @@ public class FunctionalReadWriteLock {
this(new ReentrantReadWriteLock(isFair)); this(new ReentrantReadWriteLock(isFair));
} }
private FunctionalReadWriteLock(ReadWriteLock lock) { public FunctionalReadWriteLock(ReadWriteLock lock) {
readLock = lock.readLock(); readLock = lock.readLock();
writeLock = lock.writeLock(); writeLock = lock.writeLock();
} }

View file

@ -20,7 +20,8 @@ package io.bisq.core.dao;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.google.inject.name.Names; import com.google.inject.name.Names;
import io.bisq.common.app.AppModule; import io.bisq.common.app.AppModule;
import io.bisq.core.dao.blockchain.*; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.BsqBlockChainChangeDispatcher;
import io.bisq.core.dao.blockchain.json.JsonBlockChainExporter; import io.bisq.core.dao.blockchain.json.JsonBlockChainExporter;
import io.bisq.core.dao.node.BsqNodeProvider; import io.bisq.core.dao.node.BsqNodeProvider;
import io.bisq.core.dao.node.consensus.*; import io.bisq.core.dao.node.consensus.*;
@ -63,9 +64,6 @@ public class DaoModule extends AppModule {
bind(FullNode.class).in(Singleton.class); bind(FullNode.class).in(Singleton.class);
bind(BsqNodeProvider.class).in(Singleton.class); bind(BsqNodeProvider.class).in(Singleton.class);
bind(BsqBlockChain.class).in(Singleton.class); bind(BsqBlockChain.class).in(Singleton.class);
bind(ReadModel.class).in(Singleton.class);
bind(WriteModel.class).in(Singleton.class);
bind(SnapshotManager.class).in(Singleton.class);
bind(BsqBlockChainChangeDispatcher.class).in(Singleton.class); bind(BsqBlockChainChangeDispatcher.class).in(Singleton.class);
bind(GenesisTxVerification.class).in(Singleton.class); bind(GenesisTxVerification.class).in(Singleton.class);

View file

@ -98,8 +98,8 @@ public class BsqBlockChain implements PersistableEnvelope {
private Tx genesisTx; private Tx genesisTx;
// not impl in PB yet // not impl in PB yet
private final Set<Tuple2<Long, Integer>> compensationRequestFees; private Set<Tuple2<Long, Integer>> compensationRequestFees;
private final Set<Tuple2<Long, Integer>> votingFees; private Set<Tuple2<Long, Integer>> votingFees;
// transient // transient
@Nullable @Nullable
@ -213,7 +213,7 @@ public class BsqBlockChain implements PersistableEnvelope {
// Public write access // Public write access
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
void applySnapshot() { public void applySnapshot() {
lock.write(() -> { lock.write(() -> {
checkNotNull(storage, "storage must not be null"); checkNotNull(storage, "storage must not be null");
BsqBlockChain snapshot = storage.initAndGetPersistedWithFileName("BsqBlockChain", 100); BsqBlockChain snapshot = storage.initAndGetPersistedWithFileName("BsqBlockChain", 100);
@ -238,11 +238,11 @@ public class BsqBlockChain implements PersistableEnvelope {
}); });
} }
void setCreateCompensationRequestFee(long fee, int blockHeight) { public void setCreateCompensationRequestFee(long fee, int blockHeight) {
lock.write(() -> compensationRequestFees.add(new Tuple2<>(fee, blockHeight))); lock.write(() -> compensationRequestFees.add(new Tuple2<>(fee, blockHeight)));
} }
void setVotingFee(long fee, int blockHeight) { public void setVotingFee(long fee, int blockHeight) {
lock.write(() -> votingFees.add(new Tuple2<>(fee, blockHeight))); lock.write(() -> votingFees.add(new Tuple2<>(fee, blockHeight)));
} }
@ -251,8 +251,7 @@ public class BsqBlockChain implements PersistableEnvelope {
// Package scope write access // Package scope write access
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
//TODO refactor logic out public void addBlock(BsqBlock block) throws BlockNotConnectingException {
void addBlock(BsqBlock block) throws BlockNotConnectingException {
try { try {
lock.write2(() -> { lock.write2(() -> {
if (!bsqBlocks.contains(block)) { if (!bsqBlocks.contains(block)) {
@ -283,22 +282,22 @@ public class BsqBlockChain implements PersistableEnvelope {
} }
} }
void addTxToMap(Tx tx) { public void addTxToMap(Tx tx) {
lock.write(() -> txMap.put(tx.getId(), tx)); lock.write(() -> txMap.put(tx.getId(), tx));
} }
void addUnspentTxOutput(TxOutput txOutput) { public void addUnspentTxOutput(TxOutput txOutput) {
lock.write(() -> { lock.write(() -> {
checkArgument(txOutput.isVerified(), "txOutput must be verified at addUnspentTxOutput"); checkArgument(txOutput.isVerified(), "txOutput must be verified at addUnspentTxOutput");
unspentTxOutputsMap.put(txOutput.getTxIdIndexTuple(), txOutput); unspentTxOutputsMap.put(txOutput.getTxIdIndexTuple(), txOutput);
}); });
} }
void removeUnspentTxOutput(TxOutput txOutput) { public void removeUnspentTxOutput(TxOutput txOutput) {
lock.write(() -> unspentTxOutputsMap.remove(txOutput.getTxIdIndexTuple())); lock.write(() -> unspentTxOutputsMap.remove(txOutput.getTxIdIndexTuple()));
} }
void setGenesisTx(Tx tx) { public void setGenesisTx(Tx tx) {
lock.write(() -> genesisTx = tx); lock.write(() -> genesisTx = tx);
} }
@ -323,7 +322,7 @@ public class BsqBlockChain implements PersistableEnvelope {
return lock.read(() -> (BsqBlockChain) BsqBlockChain.fromProto(bsqBlockChain.getBsqBlockChainBuilder().build())); return lock.read(() -> (BsqBlockChain) BsqBlockChain.fromProto(bsqBlockChain.getBsqBlockChainBuilder().build()));
} }
boolean containsBlock(BsqBlock bsqBlock) { public boolean containsBlock(BsqBlock bsqBlock) {
return lock.read(() -> bsqBlocks.contains(bsqBlock)); return lock.read(() -> bsqBlocks.contains(bsqBlock));
} }
@ -365,7 +364,7 @@ public class BsqBlockChain implements PersistableEnvelope {
return lock.read(() -> txMap); return lock.read(() -> txMap);
} }
List<BsqBlock> getResetBlocksFrom(int fromBlockHeight) { public List<BsqBlock> getResetBlocksFrom(int fromBlockHeight) {
return lock.read(() -> { return lock.read(() -> {
BsqBlockChain clone = getClone(); BsqBlockChain clone = getClone();
List<BsqBlock> filtered = clone.bsqBlocks.stream() List<BsqBlock> filtered = clone.bsqBlocks.stream()
@ -405,16 +404,16 @@ public class BsqBlockChain implements PersistableEnvelope {
// Package scope read access // Package scope read access
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
Optional<TxOutput> getSpendableTxOutput(String txId, int index) { public Optional<TxOutput> getSpendableTxOutput(String txId, int index) {
return lock.read(() -> getSpendableTxOutput(new TxIdIndexTuple(txId, index))); return lock.read(() -> getSpendableTxOutput(new TxIdIndexTuple(txId, index)));
} }
Optional<TxOutput> getSpendableTxOutput(TxIdIndexTuple txIdIndexTuple) { public Optional<TxOutput> getSpendableTxOutput(TxIdIndexTuple txIdIndexTuple) {
return lock.read(() -> getUnspentTxOutput(txIdIndexTuple) return lock.read(() -> getUnspentTxOutput(txIdIndexTuple)
.filter(this::isTxOutputMature)); .filter(this::isTxOutputMature));
} }
long getCreateCompensationRequestFee(int blockHeight) { public long getCreateCompensationRequestFee(int blockHeight) {
return lock.read(() -> { return lock.read(() -> {
long fee = -1; long fee = -1;
for (Tuple2<Long, Integer> feeAtHeight : compensationRequestFees) { for (Tuple2<Long, Integer> feeAtHeight : compensationRequestFees) {
@ -427,12 +426,12 @@ public class BsqBlockChain implements PersistableEnvelope {
} }
//TODO not impl yet //TODO not impl yet
boolean isCompensationRequestPeriodValid(int blockHeight) { public boolean isCompensationRequestPeriodValid(int blockHeight) {
return lock.read(() -> true); return lock.read(() -> true);
} }
long getVotingFee(int blockHeight) { public long getVotingFee(int blockHeight) {
return lock.read(() -> { return lock.read(() -> {
long fee = -1; long fee = -1;
for (Tuple2<Long, Integer> feeAtHeight : votingFees) { for (Tuple2<Long, Integer> feeAtHeight : votingFees) {
@ -445,17 +444,17 @@ public class BsqBlockChain implements PersistableEnvelope {
} }
//TODO not impl yet //TODO not impl yet
boolean isVotingPeriodValid(int blockHeight) { public boolean isVotingPeriodValid(int blockHeight) {
return lock.read(() -> true); return lock.read(() -> true);
} }
boolean existsCompensationRequestBtcAddress(String btcAddress) { public boolean existsCompensationRequestBtcAddress(String btcAddress) {
return lock.read(() -> getAllTxOutputs().stream() return lock.read(() -> getAllTxOutputs().stream()
.anyMatch(txOutput -> txOutput.isCompensationRequestBtcOutput() && .anyMatch(txOutput -> txOutput.isCompensationRequestBtcOutput() &&
btcAddress.equals(txOutput.getAddress()))); btcAddress.equals(txOutput.getAddress())));
} }
Set<TxOutput> findSponsoringBtcOutputsWithSameBtcAddress(String btcAddress) { public Set<TxOutput> findSponsoringBtcOutputsWithSameBtcAddress(String btcAddress) {
return lock.read(() -> getAllTxOutputs().stream() return lock.read(() -> getAllTxOutputs().stream()
.filter(txOutput -> txOutput.isSponsoringBtcOutput() && .filter(txOutput -> txOutput.isSponsoringBtcOutput() &&
btcAddress.equals(txOutput.getAddress())) btcAddress.equals(txOutput.getAddress()))

View file

@ -1,97 +0,0 @@
/*
* This file is part of bisq.
*
* bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bisq.core.dao.blockchain;
import io.bisq.core.dao.blockchain.vo.BsqBlock;
import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxOutput;
import io.bisq.core.dao.blockchain.vo.util.TxIdIndexTuple;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* Encapsulates read access to BsqBlockChain.
*/
public class ReadModel {
private BsqBlockChain bsqBlockChain;
@Inject
public ReadModel(BsqBlockChain bsqBlockChain) {
this.bsqBlockChain = bsqBlockChain;
}
public Optional<TxOutput> getSpendableTxOutput(TxIdIndexTuple txIdIndexTuple) {
return bsqBlockChain.getSpendableTxOutput(txIdIndexTuple);
}
public Optional<TxOutput> getSpendableTxOutput(String txId, int index) {
return getSpendableTxOutput(new TxIdIndexTuple(txId, index));
}
public boolean isCompensationRequestPeriodValid(int blockHeight) {
return bsqBlockChain.isCompensationRequestPeriodValid(blockHeight);
}
public long getCreateCompensationRequestFee(int blockHeight) {
return bsqBlockChain.getCreateCompensationRequestFee(blockHeight);
}
public int getChainHeadHeight() {
return bsqBlockChain.getChainHeadHeight();
}
public String getGenesisTxId() {
return bsqBlockChain.getGenesisTxId();
}
public int getGenesisBlockHeight() {
return bsqBlockChain.getGenesisBlockHeight();
}
public boolean containsBlock(BsqBlock bsqBlock) {
return bsqBlockChain.containsBlock(bsqBlock);
}
public List<BsqBlock> getResetBlocksFrom(int fromBlockHeight) {
return bsqBlockChain.getResetBlocksFrom(fromBlockHeight);
}
public Map<String, Tx> getTxMap() {
return bsqBlockChain.getTxMap();
}
public Tx getGenesisTx() {
return bsqBlockChain.getGenesisTx();
}
public Coin getIssuedAmount() {
return bsqBlockChain.getIssuedAmount();
}
public boolean containsTx(String txId) {
return bsqBlockChain.containsTx(txId);
}
public boolean isTxOutputSpendable(String txId, int index) {
return bsqBlockChain.isTxOutputSpendable(txId, index);
}
}

View file

@ -1,35 +0,0 @@
/*
* This file is part of bisq.
*
* bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bisq.core.dao.blockchain;
import javax.inject.Inject;
//TODO move snapshot related code from bsqBlockChain here
public class SnapshotManager {
private final BsqBlockChain bsqBlockChain;
@Inject
public SnapshotManager(BsqBlockChain bsqBlockChain) {
this.bsqBlockChain = bsqBlockChain;
}
public void applySnapshot() {
bsqBlockChain.applySnapshot();
}
}

View file

@ -1,65 +0,0 @@
/*
* This file is part of bisq.
*
* bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bisq.core.dao.blockchain;
import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException;
import io.bisq.core.dao.blockchain.vo.BsqBlock;
import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxOutput;
import javax.inject.Inject;
/**
* Encapsulates write access to BsqBlockChain.
*/
public class WriteModel {
private BsqBlockChain bsqBlockChain;
@Inject
public WriteModel(BsqBlockChain bsqBlockChain) {
this.bsqBlockChain = bsqBlockChain;
}
public void removeUnspentTxOutput(TxOutput spendableTxOutput) {
bsqBlockChain.removeUnspentTxOutput(spendableTxOutput);
}
public void addTxToMap(Tx tx) {
bsqBlockChain.addTxToMap(tx);
}
public void addUnspentTxOutput(TxOutput txOutput) {
bsqBlockChain.addUnspentTxOutput(txOutput);
}
public void setGenesisTx(Tx tx) {
bsqBlockChain.setGenesisTx(tx);
}
public void addBlock(BsqBlock bsqBlock) throws BlockNotConnectingException {
bsqBlockChain.addBlock(bsqBlock);
}
public void setCreateCompensationRequestFee(long value, int genesisBlockHeight) {
bsqBlockChain.setCreateCompensationRequestFee(value, genesisBlockHeight);
}
public void setVotingFee(long value, int genesisBlockHeight) {
bsqBlockChain.setVotingFee(value, genesisBlockHeight);
}
}

View file

@ -19,10 +19,8 @@ package io.bisq.core.dao.node;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.bisq.common.handlers.ErrorMessageHandler; import io.bisq.common.handlers.ErrorMessageHandler;
import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.BsqBlockChainListener; import io.bisq.core.dao.blockchain.BsqBlockChainListener;
import io.bisq.core.dao.blockchain.ReadModel;
import io.bisq.core.dao.blockchain.SnapshotManager;
import io.bisq.core.dao.blockchain.WriteModel;
import io.bisq.core.provider.fee.FeeService; import io.bisq.core.provider.fee.FeeService;
import io.bisq.network.p2p.P2PService; import io.bisq.network.p2p.P2PService;
import io.bisq.network.p2p.P2PServiceListener; import io.bisq.network.p2p.P2PServiceListener;
@ -42,13 +40,12 @@ public abstract class BsqNode {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected final P2PService p2PService; protected final P2PService p2PService;
protected final ReadModel readModel; @SuppressWarnings("WeakerAccess")
protected final BsqBlockChain bsqBlockChain;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected final List<BsqBlockChainListener> bsqBlockChainListeners = new ArrayList<>(); protected final List<BsqBlockChainListener> bsqBlockChainListeners = new ArrayList<>();
private final String genesisTxId; private final String genesisTxId;
private final int genesisBlockHeight; private final int genesisBlockHeight;
private final SnapshotManager snapshotManager;
@org.jetbrains.annotations.NotNull
@Getter @Getter
protected boolean parseBlockchainComplete; protected boolean parseBlockchainComplete;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@ -60,22 +57,19 @@ public abstract class BsqNode {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@Inject @Inject
public BsqNode(WriteModel writeModel, public BsqNode(P2PService p2PService,
ReadModel readModel, BsqBlockChain bsqBlockChain,
SnapshotManager snapshotManager,
P2PService p2PService,
FeeService feeService) { FeeService feeService) {
this.p2PService = p2PService; this.p2PService = p2PService;
this.readModel = readModel; this.bsqBlockChain = bsqBlockChain;
genesisTxId = readModel.getGenesisTxId(); genesisTxId = bsqBlockChain.getGenesisTxId();
genesisBlockHeight = readModel.getGenesisBlockHeight(); genesisBlockHeight = bsqBlockChain.getGenesisBlockHeight();
this.snapshotManager = snapshotManager;
writeModel.setCreateCompensationRequestFee(feeService.getCreateCompensationRequestFee().value, bsqBlockChain.setCreateCompensationRequestFee(feeService.getCreateCompensationRequestFee().value,
genesisBlockHeight); genesisBlockHeight);
writeModel.setVotingFee(feeService.getVotingTxFee().value, bsqBlockChain.setVotingFee(feeService.getVotingTxFee().value,
genesisBlockHeight); genesisBlockHeight);
} }
@ -156,16 +150,16 @@ public abstract class BsqNode {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected int getStartBlockHeight() { protected int getStartBlockHeight() {
final int startBlockHeight = Math.max(genesisBlockHeight, readModel.getChainHeadHeight() + 1); final int startBlockHeight = Math.max(genesisBlockHeight, bsqBlockChain.getChainHeadHeight() + 1);
log.info("Start parse blocks:\n" + log.info("Start parse blocks:\n" +
" Start block height={}\n" + " Start block height={}\n" +
" Genesis txId={}\n" + " Genesis txId={}\n" +
" Genesis block height={}\n" + " Genesis block height={}\n" +
" Block height={}\n", " BsqBlockChain block height={}\n",
startBlockHeight, startBlockHeight,
genesisTxId, genesisTxId,
genesisBlockHeight, genesisBlockHeight,
readModel.getChainHeadHeight()); bsqBlockChain.getChainHeadHeight());
return startBlockHeight; return startBlockHeight;
} }
@ -188,7 +182,7 @@ public abstract class BsqNode {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private void applySnapshot() { private void applySnapshot() {
snapshotManager.applySnapshot(); bsqBlockChain.applySnapshot();
bsqBlockChainListeners.forEach(BsqBlockChainListener::onBsqBlockChainChanged); bsqBlockChainListeners.forEach(BsqBlockChainListener::onBsqBlockChainChanged);
} }
} }

View file

@ -18,7 +18,7 @@
package io.bisq.core.dao.node; package io.bisq.core.dao.node;
import io.bisq.common.app.DevEnv; import io.bisq.common.app.DevEnv;
import io.bisq.core.dao.blockchain.WriteModel; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.Tx; import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxInput; import io.bisq.core.dao.blockchain.vo.TxInput;
import io.bisq.core.dao.node.consensus.BsqTxVerification; import io.bisq.core.dao.node.consensus.BsqTxVerification;
@ -44,7 +44,7 @@ import static com.google.common.base.Preconditions.checkArgument;
@Slf4j @Slf4j
@Immutable @Immutable
public abstract class BsqParser { public abstract class BsqParser {
protected final WriteModel writeModel; protected final BsqBlockChain bsqBlockChain;
private final GenesisTxVerification genesisTxVerification; private final GenesisTxVerification genesisTxVerification;
private final BsqTxVerification bsqTxVerification; private final BsqTxVerification bsqTxVerification;
@ -55,10 +55,10 @@ public abstract class BsqParser {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@Inject @Inject
public BsqParser(WriteModel writeModel, public BsqParser(BsqBlockChain bsqBlockChain,
GenesisTxVerification genesisTxVerification, GenesisTxVerification genesisTxVerification,
BsqTxVerification bsqTxVerification) { BsqTxVerification bsqTxVerification) {
this.writeModel = writeModel; this.bsqBlockChain = bsqBlockChain;
this.genesisTxVerification = genesisTxVerification; this.genesisTxVerification = genesisTxVerification;
this.bsqTxVerification = bsqTxVerification; this.bsqTxVerification = bsqTxVerification;
} }

View file

@ -17,6 +17,7 @@
package io.bisq.core.dao.node.consensus; package io.bisq.core.dao.node.consensus;
import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.Tx; import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxType; import io.bisq.core.dao.blockchain.vo.TxType;
import lombok.Getter; import lombok.Getter;
@ -31,17 +32,26 @@ import javax.inject.Inject;
@Slf4j @Slf4j
public class BsqTxVerification { public class BsqTxVerification {
private final BsqBlockChain bsqBlockChain;
private final TxInputsVerification txInputsVerification; private final TxInputsVerification txInputsVerification;
private final TxOutputsVerification txOutputsVerification; private final TxOutputsVerification txOutputsVerification;
@Inject @Inject
public BsqTxVerification(TxInputsVerification txInputsVerification, public BsqTxVerification(BsqBlockChain bsqBlockChain,
TxInputsVerification txInputsVerification,
TxOutputsVerification txOutputsVerification) { TxOutputsVerification txOutputsVerification) {
this.bsqBlockChain = bsqBlockChain;
this.txInputsVerification = txInputsVerification; this.txInputsVerification = txInputsVerification;
this.txOutputsVerification = txOutputsVerification; this.txOutputsVerification = txOutputsVerification;
} }
public boolean isBsqTx(int blockHeight, Tx tx) { public boolean isBsqTx(int blockHeight, Tx tx) {
return bsqBlockChain.<Boolean>callFunctionWithWriteLock(() -> execute(blockHeight, tx));
}
// Not thread safe wrt bsqBlockChain
// Check if any of the inputs are BSQ inputs and update BsqBlockChain state accordingly
private boolean execute(int blockHeight, Tx tx) {
BsqInputBalance bsqInputBalance = txInputsVerification.getBsqInputBalance(tx, blockHeight); BsqInputBalance bsqInputBalance = txInputsVerification.getBsqInputBalance(tx, blockHeight);
final boolean bsqInputBalancePositive = bsqInputBalance.isPositive(); final boolean bsqInputBalancePositive = bsqInputBalance.isPositive();

View file

@ -18,7 +18,7 @@
package io.bisq.core.dao.node.consensus; package io.bisq.core.dao.node.consensus;
import io.bisq.common.app.Version; import io.bisq.common.app.Version;
import io.bisq.core.dao.blockchain.ReadModel; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.Tx; import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxOutput; import io.bisq.core.dao.blockchain.vo.TxOutput;
import io.bisq.core.dao.blockchain.vo.TxOutputType; import io.bisq.core.dao.blockchain.vo.TxOutputType;
@ -26,30 +26,27 @@ import io.bisq.core.dao.blockchain.vo.TxType;
import javax.inject.Inject; import javax.inject.Inject;
import static com.google.common.base.Preconditions.checkArgument;
/** /**
* Verifies if OP_RETURN data matches rules for a compensation request tx and applies state change. * Verifies if OP_RETURN data matches rules for a compensation request tx and applies state change.
*/ */
public class CompensationRequestVerification { public class CompensationRequestVerification {
private final ReadModel readModel; private final BsqBlockChain bsqBlockChain;
@Inject @Inject
public CompensationRequestVerification(ReadModel readModel) { public CompensationRequestVerification(BsqBlockChain bsqBlockChain) {
this.readModel = readModel; this.bsqBlockChain = bsqBlockChain;
} }
public boolean verify(byte[] opReturnData, long bsqFee, int blockHeight, TxOutputsVerification.MutableState mutableState) { public boolean verify(byte[] opReturnData, long bsqFee, int blockHeight, TxOutputsVerification.MutableState mutableState) {
return mutableState.getCompRequestIssuanceOutputCandidate() != null && return mutableState.getCompRequestIssuanceOutputCandidate() != null &&
opReturnData.length == 22 && opReturnData.length == 22 &&
Version.COMPENSATION_REQUEST_VERSION == opReturnData[1] && Version.COMPENSATION_REQUEST_VERSION == opReturnData[1] &&
bsqFee == readModel.getCreateCompensationRequestFee(blockHeight) && bsqFee == bsqBlockChain.getCreateCompensationRequestFee(blockHeight) &&
readModel.isCompensationRequestPeriodValid(blockHeight); bsqBlockChain.isCompensationRequestPeriodValid(blockHeight);
} }
public void applyStateChange(Tx tx, TxOutput opReturnTxOutput, TxOutputsVerification.MutableState mutableState) { public void applyStateChange(Tx tx, TxOutput opReturnTxOutput, TxOutputsVerification.MutableState mutableState) {
opReturnTxOutput.setTxOutputType(TxOutputType.COMPENSATION_REQUEST_OP_RETURN_OUTPUT); opReturnTxOutput.setTxOutputType(TxOutputType.COMPENSATION_REQUEST_OP_RETURN_OUTPUT);
checkArgument(mutableState.getCompRequestIssuanceOutputCandidate() != null, "mutableState.getCompRequestIssuanceOutputCandidate() must nto be null");
mutableState.getCompRequestIssuanceOutputCandidate().setTxOutputType(TxOutputType.COMPENSATION_REQUEST_ISSUANCE_CANDIDATE_OUTPUT); mutableState.getCompRequestIssuanceOutputCandidate().setTxOutputType(TxOutputType.COMPENSATION_REQUEST_ISSUANCE_CANDIDATE_OUTPUT);
tx.setTxType(TxType.COMPENSATION_REQUEST); tx.setTxType(TxType.COMPENSATION_REQUEST);
} }

View file

@ -18,7 +18,7 @@
package io.bisq.core.dao.node.consensus; package io.bisq.core.dao.node.consensus;
import io.bisq.core.dao.DaoOptionKeys; import io.bisq.core.dao.DaoOptionKeys;
import io.bisq.core.dao.blockchain.WriteModel; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.Tx; import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxType; import io.bisq.core.dao.blockchain.vo.TxType;
@ -30,15 +30,15 @@ import javax.inject.Named;
*/ */
public class GenesisTxVerification { public class GenesisTxVerification {
private final WriteModel writeModel; private final BsqBlockChain bsqBlockChain;
private final String genesisTxId; private final String genesisTxId;
private final int genesisBlockHeight; private final int genesisBlockHeight;
@Inject @Inject
public GenesisTxVerification(WriteModel writeModel, public GenesisTxVerification(BsqBlockChain bsqBlockChain,
@Named(DaoOptionKeys.GENESIS_TX_ID) String genesisTxId, @Named(DaoOptionKeys.GENESIS_TX_ID) String genesisTxId,
@Named(DaoOptionKeys.GENESIS_BLOCK_HEIGHT) int genesisBlockHeight) { @Named(DaoOptionKeys.GENESIS_BLOCK_HEIGHT) int genesisBlockHeight) {
this.writeModel = writeModel; this.bsqBlockChain = bsqBlockChain;
this.genesisTxId = genesisTxId; this.genesisTxId = genesisTxId;
this.genesisBlockHeight = genesisBlockHeight; this.genesisBlockHeight = genesisBlockHeight;
} }
@ -51,11 +51,11 @@ public class GenesisTxVerification {
tx.getOutputs().forEach(txOutput -> { tx.getOutputs().forEach(txOutput -> {
txOutput.setUnspent(true); txOutput.setUnspent(true);
txOutput.setVerified(true); txOutput.setVerified(true);
writeModel.addUnspentTxOutput(txOutput); bsqBlockChain.addUnspentTxOutput(txOutput);
}); });
tx.setTxType(TxType.GENESIS); tx.setTxType(TxType.GENESIS);
writeModel.setGenesisTx(tx); bsqBlockChain.setGenesisTx(tx);
writeModel.addTxToMap(tx); bsqBlockChain.addTxToMap(tx);
} }
} }

View file

@ -17,20 +17,42 @@
package io.bisq.core.dao.node.consensus; package io.bisq.core.dao.node.consensus;
import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxOutput;
import io.bisq.core.dao.blockchain.vo.TxType;
import io.bisq.core.dao.request.compensation.CompensationRequest;
import io.bisq.core.dao.request.compensation.CompensationRequestManager;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.List;
import java.util.Optional;
import java.util.Set;
//TODO outdated, ignore
@Slf4j @Slf4j
public class IssuanceVerification { public class IssuanceVerification {
/* private static final long MIN_BSQ_ISSUANCE_AMOUNT = 1000; private static final long MIN_BSQ_ISSUANCE_AMOUNT = 1000;
private static final long MAX_BSQ_ISSUANCE_AMOUNT = 10_000_000;*/ private static final long MAX_BSQ_ISSUANCE_AMOUNT = 10_000_000;
private final BsqBlockChain bsqBlockChain;
private final PeriodVerification periodVerification;
private final VotingVerification votingVerification;
private final CompensationRequestManager compensationRequestManager;
@Inject @Inject
public IssuanceVerification() { public IssuanceVerification(BsqBlockChain bsqBlockChain,
PeriodVerification periodVerification,
VotingVerification votingVerification,
CompensationRequestManager compensationRequestManager) {
this.bsqBlockChain = bsqBlockChain;
this.periodVerification = periodVerification;
this.votingVerification = votingVerification;
this.compensationRequestManager = compensationRequestManager;
} }
/* public boolean maybeProcessData(Tx tx) { public boolean maybeProcessData(Tx tx) {
List<TxOutput> outputs = tx.getOutputs(); List<TxOutput> outputs = tx.getOutputs();
if (outputs.size() >= 2) { if (outputs.size() >= 2) {
TxOutput bsqTxOutput = outputs.get(0); TxOutput bsqTxOutput = outputs.get(0);
@ -69,5 +91,5 @@ public class IssuanceVerification {
} }
} }
return false; return false;
}*/ }
} }

View file

@ -17,11 +17,20 @@
package io.bisq.core.dao.node.consensus; package io.bisq.core.dao.node.consensus;
import io.bisq.core.dao.blockchain.BsqBlockChain;
import javax.inject.Inject; import javax.inject.Inject;
public class PeriodVerification { public class PeriodVerification {
private final BsqBlockChain bsqBlockChain;
@Inject @Inject
public PeriodVerification() { public PeriodVerification(BsqBlockChain bsqBlockChain) {
this.bsqBlockChain = bsqBlockChain;
}
// TODO
public boolean isInSponsorPeriod(int blockHeight) {
return true;
} }
} }

View file

@ -17,8 +17,7 @@
package io.bisq.core.dao.node.consensus; package io.bisq.core.dao.node.consensus;
import io.bisq.core.dao.blockchain.ReadModel; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.WriteModel;
import io.bisq.core.dao.blockchain.vo.SpentInfo; import io.bisq.core.dao.blockchain.vo.SpentInfo;
import io.bisq.core.dao.blockchain.vo.Tx; import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxInput; import io.bisq.core.dao.blockchain.vo.TxInput;
@ -35,25 +34,23 @@ import java.util.Optional;
@Slf4j @Slf4j
public class TxInputVerification { public class TxInputVerification {
private final WriteModel writeModel; private final BsqBlockChain bsqBlockChain;
private final ReadModel readModel;
@Inject @Inject
public TxInputVerification(WriteModel writeModel, ReadModel readModel) { public TxInputVerification(BsqBlockChain bsqBlockChain) {
this.writeModel = writeModel; this.bsqBlockChain = bsqBlockChain;
this.readModel = readModel;
} }
Optional<TxOutput> getOptionalSpendableTxOutput(TxInput input) { Optional<TxOutput> getOptionalSpendableTxOutput(TxInput input) {
// TODO check if Tuple indexes of inputs outputs are not messed up... // TODO check if Tuple indexes of inputs outputs are not messed up...
// Get spendable BSQ output for txIdIndexTuple... (get output used as input in tx if it's spendable BSQ) // Get spendable BSQ output for txIdIndexTuple... (get output used as input in tx if it's spendable BSQ)
return readModel.getSpendableTxOutput(input.getTxIdIndexTuple()); return bsqBlockChain.getSpendableTxOutput(input.getTxIdIndexTuple());
} }
void applyStateChange(TxInput input, TxOutput spendableTxOutput, int blockHeight, Tx tx, int inputIndex) { void applyStateChange(TxInput input, TxOutput spendableTxOutput, int blockHeight, Tx tx, int inputIndex) {
// The output is BSQ, set it as spent, update bsqBlockChain and add to available BSQ for this tx // The output is BSQ, set it as spent, update bsqBlockChain and add to available BSQ for this tx
spendableTxOutput.setUnspent(false); spendableTxOutput.setUnspent(false);
writeModel.removeUnspentTxOutput(spendableTxOutput); bsqBlockChain.removeUnspentTxOutput(spendableTxOutput);
spendableTxOutput.setSpentInfo(new SpentInfo(blockHeight, tx.getId(), inputIndex)); spendableTxOutput.setSpentInfo(new SpentInfo(blockHeight, tx.getId(), inputIndex));
input.setConnectedTxOutput(spendableTxOutput); input.setConnectedTxOutput(spendableTxOutput);
} }

View file

@ -17,7 +17,7 @@
package io.bisq.core.dao.node.consensus; package io.bisq.core.dao.node.consensus;
import io.bisq.core.dao.blockchain.WriteModel; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.Tx; import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxInput; import io.bisq.core.dao.blockchain.vo.TxInput;
import io.bisq.core.dao.blockchain.vo.TxOutput; import io.bisq.core.dao.blockchain.vo.TxOutput;
@ -32,12 +32,12 @@ import java.util.Optional;
@Slf4j @Slf4j
public class TxInputsVerification { public class TxInputsVerification {
private final WriteModel writeModel; private final BsqBlockChain bsqBlockChain;
private final TxInputVerification txInputVerification; private final TxInputVerification txInputVerification;
@Inject @Inject
public TxInputsVerification(WriteModel writeModel, TxInputVerification txInputVerification) { public TxInputsVerification(BsqBlockChain bsqBlockChain, TxInputVerification txInputVerification) {
this.writeModel = writeModel; this.bsqBlockChain = bsqBlockChain;
this.txInputVerification = txInputVerification; this.txInputVerification = txInputVerification;
} }
@ -55,6 +55,6 @@ public class TxInputsVerification {
} }
void applyStateChange(Tx tx) { void applyStateChange(Tx tx) {
writeModel.addTxToMap(tx); bsqBlockChain.addTxToMap(tx);
} }
} }

View file

@ -17,7 +17,7 @@
package io.bisq.core.dao.node.consensus; package io.bisq.core.dao.node.consensus;
import io.bisq.core.dao.blockchain.WriteModel; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.Tx; import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxOutput; import io.bisq.core.dao.blockchain.vo.TxOutput;
import io.bisq.core.dao.blockchain.vo.TxOutputType; import io.bisq.core.dao.blockchain.vo.TxOutputType;
@ -34,12 +34,13 @@ import static com.google.common.base.Preconditions.checkArgument;
@Slf4j @Slf4j
public class TxOutputVerification { public class TxOutputVerification {
private final WriteModel writeModel; private final BsqBlockChain bsqBlockChain;
private final OpReturnVerification opReturnVerification; private final OpReturnVerification opReturnVerification;
@Inject @Inject
public TxOutputVerification(WriteModel writeModel, OpReturnVerification opReturnVerification) { public TxOutputVerification(BsqBlockChain bsqBlockChain,
this.writeModel = writeModel; OpReturnVerification opReturnVerification) {
this.bsqBlockChain = bsqBlockChain;
this.opReturnVerification = opReturnVerification; this.opReturnVerification = opReturnVerification;
} }
@ -99,7 +100,7 @@ public class TxOutputVerification {
txOutput.setVerified(true); txOutput.setVerified(true);
txOutput.setUnspent(true); txOutput.setUnspent(true);
txOutput.setTxOutputType(TxOutputType.BSQ_OUTPUT); txOutput.setTxOutputType(TxOutputType.BSQ_OUTPUT);
writeModel.addUnspentTxOutput(txOutput); bsqBlockChain.addUnspentTxOutput(txOutput);
} }
private void applyStateChangeForBtcOutput(TxOutput txOutput) { private void applyStateChangeForBtcOutput(TxOutput txOutput) {

View file

@ -23,7 +23,6 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.List; import java.util.List;
@ -53,9 +52,7 @@ public class TxOutputsVerification {
@Getter @Getter
@Setter @Setter
static class MutableState { static class MutableState {
@Nullable
private TxOutput compRequestIssuanceOutputCandidate; private TxOutput compRequestIssuanceOutputCandidate;
@Nullable
private TxOutput bsqOutput; private TxOutput bsqOutput;
MutableState() { MutableState() {

View file

@ -17,14 +17,54 @@
package io.bisq.core.dao.node.consensus; package io.bisq.core.dao.node.consensus;
import io.bisq.common.app.Version;
import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxOutput;
import io.bisq.core.dao.blockchain.vo.TxOutputType;
import io.bisq.core.dao.blockchain.vo.TxType;
import io.bisq.core.dao.request.compensation.CompensationRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import javax.inject.Inject; import javax.inject.Inject;
//TODO outdated, ignore
@SuppressWarnings("unused")
@Slf4j @Slf4j
public class VotingVerification { public class VotingVerification {
private final BsqBlockChain bsqBlockChain;
private final PeriodVerification periodVerification;
@Inject @Inject
public VotingVerification() { public VotingVerification(BsqBlockChain bsqBlockChain,
PeriodVerification periodVerification) {
this.bsqBlockChain = bsqBlockChain;
this.periodVerification = periodVerification;
}
public boolean isCompensationRequestAccepted(CompensationRequest compensationRequest) {
return true;
}
public boolean isConversionRateValid(int blockHeight, long btcAmount, long bsqAmount) {
return false;
}
public boolean isOpReturn(Tx tx, byte[] opReturnData, TxOutput txOutput, long bsqFee, int blockHeight, TxOutput bsqOutput) {
if (Version.VOTING_VERSION == opReturnData[1] && opReturnData.length > 22) {
final int sizeOfCompRequestsVotes = (int) opReturnData[22];
if (bsqOutput != null &&
sizeOfCompRequestsVotes % 2 == 0 &&
opReturnData.length % 2 == 1 &&
opReturnData.length >= 23 + sizeOfCompRequestsVotes * 2 &&
bsqFee == bsqBlockChain.getVotingFee(blockHeight) &&
bsqBlockChain.isVotingPeriodValid(blockHeight)) {
txOutput.setTxOutputType(TxOutputType.VOTE_OP_RETURN_OUTPUT);
tx.setTxType(TxType.VOTE);
// TODO use bsqOutput as weight
return true;
}
}
return false;
} }
} }

View file

@ -20,10 +20,8 @@ package io.bisq.core.dao.node.full;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.bisq.common.UserThread; import io.bisq.common.UserThread;
import io.bisq.common.handlers.ErrorMessageHandler; import io.bisq.common.handlers.ErrorMessageHandler;
import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.BsqBlockChainListener; import io.bisq.core.dao.blockchain.BsqBlockChainListener;
import io.bisq.core.dao.blockchain.ReadModel;
import io.bisq.core.dao.blockchain.SnapshotManager;
import io.bisq.core.dao.blockchain.WriteModel;
import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException; import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException;
import io.bisq.core.dao.blockchain.json.JsonBlockChainExporter; import io.bisq.core.dao.blockchain.json.JsonBlockChainExporter;
import io.bisq.core.dao.blockchain.vo.BsqBlock; import io.bisq.core.dao.blockchain.vo.BsqBlock;
@ -51,18 +49,14 @@ public class FullNode extends BsqNode {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@Inject @Inject
public FullNode(WriteModel writeModel, public FullNode(P2PService p2PService,
ReadModel readModel,
SnapshotManager snapshotManager,
P2PService p2PService,
FullNodeExecutor bsqFullNodeExecutor, FullNodeExecutor bsqFullNodeExecutor,
BsqBlockChain bsqBlockChain,
JsonBlockChainExporter jsonBlockChainExporter, JsonBlockChainExporter jsonBlockChainExporter,
FeeService feeService, FeeService feeService,
FullNodeNetworkManager fullNodeNetworkManager) { FullNodeNetworkManager fullNodeNetworkManager) {
super(writeModel, super(p2PService,
readModel, bsqBlockChain,
snapshotManager,
p2PService,
feeService); feeService);
this.bsqFullNodeExecutor = bsqFullNodeExecutor; this.bsqFullNodeExecutor = bsqFullNodeExecutor;
this.jsonBlockChainExporter = jsonBlockChainExporter; this.jsonBlockChainExporter = jsonBlockChainExporter;

View file

@ -20,7 +20,7 @@ package io.bisq.core.dao.node.full;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.neemre.btcdcli4j.core.domain.Block; import com.neemre.btcdcli4j.core.domain.Block;
import io.bisq.core.dao.blockchain.WriteModel; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException; import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException;
import io.bisq.core.dao.blockchain.exceptions.BsqBlockchainException; import io.bisq.core.dao.blockchain.exceptions.BsqBlockchainException;
import io.bisq.core.dao.blockchain.vo.BsqBlock; import io.bisq.core.dao.blockchain.vo.BsqBlock;
@ -57,10 +57,10 @@ public class FullNodeParser extends BsqParser {
@Inject @Inject
public FullNodeParser(RpcService rpcService, public FullNodeParser(RpcService rpcService,
WriteModel writeModel, BsqBlockChain bsqBlockChain,
GenesisTxVerification genesisTxVerification, GenesisTxVerification genesisTxVerification,
BsqTxVerification bsqTxVerification) { BsqTxVerification bsqTxVerification) {
super(writeModel, genesisTxVerification, bsqTxVerification); super(bsqBlockChain, genesisTxVerification, bsqTxVerification);
this.rpcService = rpcService; this.rpcService = rpcService;
} }
@ -95,7 +95,7 @@ public class FullNodeParser extends BsqParser {
btcdBlock.getHash(), btcdBlock.getHash(),
btcdBlock.getPreviousBlockHash(), btcdBlock.getPreviousBlockHash(),
ImmutableList.copyOf(bsqTxsInBlock)); ImmutableList.copyOf(bsqTxsInBlock));
writeModel.addBlock(bsqBlock); bsqBlockChain.addBlock(bsqBlock);
log.info("parseBlock took {} ms at blockHeight {}; bsqTxsInBlock.size={}", log.info("parseBlock took {} ms at blockHeight {}; bsqTxsInBlock.size={}",
System.currentTimeMillis() - startTs, bsqBlock.getHeight(), bsqTxsInBlock.size()); System.currentTimeMillis() - startTs, bsqBlock.getHeight(), bsqTxsInBlock.size());
return bsqBlock; return bsqBlock;

View file

@ -3,7 +3,7 @@ package io.bisq.core.dao.node.full.network;
import io.bisq.common.UserThread; import io.bisq.common.UserThread;
import io.bisq.common.app.Log; import io.bisq.common.app.Log;
import io.bisq.common.proto.network.NetworkEnvelope; import io.bisq.common.proto.network.NetworkEnvelope;
import io.bisq.core.dao.blockchain.ReadModel; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.BsqBlock; import io.bisq.core.dao.blockchain.vo.BsqBlock;
import io.bisq.core.dao.node.messages.GetBsqBlocksRequest; import io.bisq.core.dao.node.messages.GetBsqBlocksRequest;
import io.bisq.core.dao.node.messages.NewBsqBlockBroadcastMessage; import io.bisq.core.dao.node.messages.NewBsqBlockBroadcastMessage;
@ -35,7 +35,7 @@ public class FullNodeNetworkManager implements MessageListener, PeerManager.List
private final NetworkNode networkNode; private final NetworkNode networkNode;
private final PeerManager peerManager; private final PeerManager peerManager;
private final Broadcaster broadcaster; private final Broadcaster broadcaster;
private final ReadModel readModel; private final BsqBlockChain bsqBlockChain;
// Key is connection UID // Key is connection UID
private final Map<String, GetBsqBlocksRequestHandler> getBlocksRequestHandlers = new HashMap<>(); private final Map<String, GetBsqBlocksRequestHandler> getBlocksRequestHandlers = new HashMap<>();
@ -50,11 +50,11 @@ public class FullNodeNetworkManager implements MessageListener, PeerManager.List
public FullNodeNetworkManager(NetworkNode networkNode, public FullNodeNetworkManager(NetworkNode networkNode,
PeerManager peerManager, PeerManager peerManager,
Broadcaster broadcaster, Broadcaster broadcaster,
ReadModel readModel) { BsqBlockChain bsqBlockChain) {
this.networkNode = networkNode; this.networkNode = networkNode;
this.peerManager = peerManager; this.peerManager = peerManager;
this.broadcaster = broadcaster; this.broadcaster = broadcaster;
this.readModel = readModel; this.bsqBlockChain = bsqBlockChain;
// seedNodeAddresses can be empty (in case there is only 1 seed node, the seed node starting up has no other seed nodes) // seedNodeAddresses can be empty (in case there is only 1 seed node, the seed node starting up has no other seed nodes)
networkNode.addMessageListener(this); networkNode.addMessageListener(this);
@ -113,7 +113,7 @@ public class FullNodeNetworkManager implements MessageListener, PeerManager.List
final String uid = connection.getUid(); final String uid = connection.getUid();
if (!getBlocksRequestHandlers.containsKey(uid)) { if (!getBlocksRequestHandlers.containsKey(uid)) {
GetBsqBlocksRequestHandler requestHandler = new GetBsqBlocksRequestHandler(networkNode, GetBsqBlocksRequestHandler requestHandler = new GetBsqBlocksRequestHandler(networkNode,
readModel, bsqBlockChain,
new GetBsqBlocksRequestHandler.Listener() { new GetBsqBlocksRequestHandler.Listener() {
@Override @Override
public void onComplete() { public void onComplete() {

View file

@ -6,7 +6,7 @@ import com.google.common.util.concurrent.SettableFuture;
import io.bisq.common.Timer; import io.bisq.common.Timer;
import io.bisq.common.UserThread; import io.bisq.common.UserThread;
import io.bisq.common.app.Log; import io.bisq.common.app.Log;
import io.bisq.core.dao.blockchain.ReadModel; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.BsqBlock; import io.bisq.core.dao.blockchain.vo.BsqBlock;
import io.bisq.core.dao.node.messages.GetBsqBlocksRequest; import io.bisq.core.dao.node.messages.GetBsqBlocksRequest;
import io.bisq.core.dao.node.messages.GetBsqBlocksResponse; import io.bisq.core.dao.node.messages.GetBsqBlocksResponse;
@ -43,19 +43,19 @@ class GetBsqBlocksRequestHandler {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private final NetworkNode networkNode; private final NetworkNode networkNode;
private final ReadModel readModel;
private final Listener listener; private final Listener listener;
private Timer timeoutTimer; private Timer timeoutTimer;
private boolean stopped; private boolean stopped;
private final BsqBlockChain bsqBlockChain;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Constructor // Constructor
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public GetBsqBlocksRequestHandler(NetworkNode networkNode, ReadModel readModel, Listener listener) { public GetBsqBlocksRequestHandler(NetworkNode networkNode, BsqBlockChain bsqBlockChain, Listener listener) {
this.networkNode = networkNode; this.networkNode = networkNode;
this.readModel = readModel; this.bsqBlockChain = bsqBlockChain;
this.listener = listener; this.listener = listener;
} }
@ -66,7 +66,7 @@ class GetBsqBlocksRequestHandler {
public void onGetBsqBlocksRequest(GetBsqBlocksRequest getBsqBlocksRequest, final Connection connection) { public void onGetBsqBlocksRequest(GetBsqBlocksRequest getBsqBlocksRequest, final Connection connection) {
Log.traceCall(getBsqBlocksRequest + "\n\tconnection=" + connection); Log.traceCall(getBsqBlocksRequest + "\n\tconnection=" + connection);
List<BsqBlock> bsqBlocks = readModel.getResetBlocksFrom(getBsqBlocksRequest.getFromBlockHeight()); List<BsqBlock> bsqBlocks = bsqBlockChain.getResetBlocksFrom(getBsqBlocksRequest.getFromBlockHeight());
final GetBsqBlocksResponse bsqBlocksResponse = new GetBsqBlocksResponse(bsqBlocks, getBsqBlocksRequest.getNonce()); final GetBsqBlocksResponse bsqBlocksResponse = new GetBsqBlocksResponse(bsqBlocks, getBsqBlocksRequest.getNonce());
log.debug("bsqBlocksResponse " + bsqBlocksResponse.getRequestNonce()); log.debug("bsqBlocksResponse " + bsqBlocksResponse.getRequestNonce());

View file

@ -20,10 +20,8 @@ package io.bisq.core.dao.node.lite;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.bisq.common.UserThread; import io.bisq.common.UserThread;
import io.bisq.common.handlers.ErrorMessageHandler; import io.bisq.common.handlers.ErrorMessageHandler;
import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.BsqBlockChainListener; import io.bisq.core.dao.blockchain.BsqBlockChainListener;
import io.bisq.core.dao.blockchain.ReadModel;
import io.bisq.core.dao.blockchain.SnapshotManager;
import io.bisq.core.dao.blockchain.WriteModel;
import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException; import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException;
import io.bisq.core.dao.blockchain.vo.BsqBlock; import io.bisq.core.dao.blockchain.vo.BsqBlock;
import io.bisq.core.dao.node.BsqNode; import io.bisq.core.dao.node.BsqNode;
@ -43,7 +41,7 @@ import java.util.function.Consumer;
/** /**
* Main class for lite nodes which receive the BSQ transactions from a full node (e.g. seed nodes). * Main class for lite nodes which receive the BSQ transactions from a full node (e.g. seed nodes).
* <p> *
* Verification of BSQ transactions is done also by the lite node. * Verification of BSQ transactions is done also by the lite node.
*/ */
@Slf4j @Slf4j
@ -58,17 +56,13 @@ public class LiteNode extends BsqNode {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@Inject @Inject
public LiteNode(WriteModel writeModel, public LiteNode(P2PService p2PService,
ReadModel readModel,
SnapshotManager snapshotManager,
P2PService p2PService,
LiteNodeExecutor bsqLiteNodeExecutor, LiteNodeExecutor bsqLiteNodeExecutor,
BsqBlockChain bsqBlockChain,
FeeService feeService, FeeService feeService,
LiteNodeNetworkManager liteNodeNetworkManager) { LiteNodeNetworkManager liteNodeNetworkManager) {
super(writeModel, super(p2PService,
readModel, bsqBlockChain,
snapshotManager,
p2PService,
feeService); feeService);
this.bsqLiteNodeExecutor = bsqLiteNodeExecutor; this.bsqLiteNodeExecutor = bsqLiteNodeExecutor;
this.liteNodeNetworkManager = liteNodeNetworkManager; this.liteNodeNetworkManager = liteNodeNetworkManager;
@ -150,7 +144,7 @@ public class LiteNode extends BsqNode {
// We reset all mutable data in case the provider would not have done it. // We reset all mutable data in case the provider would not have done it.
bsqBlock.reset(); bsqBlock.reset();
log.info("onNewBlockReceived: bsqBlock={}", bsqBlock.getHeight()); log.info("onNewBlockReceived: bsqBlock={}", bsqBlock.getHeight());
if (!readModel.containsBlock(bsqBlock)) { if (!bsqBlockChain.containsBlock(bsqBlock)) {
bsqLiteNodeExecutor.parseBlock(bsqBlock, bsqLiteNodeExecutor.parseBlock(bsqBlock,
this::notifyListenersOnNewBlock, this::notifyListenersOnNewBlock,
getErrorHandler()); getErrorHandler());

View file

@ -24,6 +24,7 @@ import com.google.common.util.concurrent.ListeningExecutorService;
import io.bisq.common.UserThread; import io.bisq.common.UserThread;
import io.bisq.common.handlers.ResultHandler; import io.bisq.common.handlers.ResultHandler;
import io.bisq.common.util.Utilities; import io.bisq.common.util.Utilities;
import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.vo.BsqBlock; import io.bisq.core.dao.blockchain.vo.BsqBlock;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -39,6 +40,7 @@ import java.util.function.Consumer;
public class LiteNodeExecutor { public class LiteNodeExecutor {
private final LiteNodeParser liteNodeParser; private final LiteNodeParser liteNodeParser;
private final BsqBlockChain bsqBlockChain;
private final ListeningExecutorService parseBlocksExecutor = Utilities.getListeningExecutorService("ParseBlocks", 1, 1, 60); private final ListeningExecutorService parseBlocksExecutor = Utilities.getListeningExecutorService("ParseBlocks", 1, 1, 60);
private final ListeningExecutorService parseBlockExecutor = Utilities.getListeningExecutorService("ParseBlock", 1, 1, 60); private final ListeningExecutorService parseBlockExecutor = Utilities.getListeningExecutorService("ParseBlock", 1, 1, 60);
@ -50,8 +52,9 @@ public class LiteNodeExecutor {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@Inject @Inject
public LiteNodeExecutor(LiteNodeParser liteNodeParser) { public LiteNodeExecutor(LiteNodeParser liteNodeParser, BsqBlockChain bsqBlockChain) {
this.liteNodeParser = liteNodeParser; this.liteNodeParser = liteNodeParser;
this.bsqBlockChain = bsqBlockChain;
} }
@ -91,6 +94,7 @@ public class LiteNodeExecutor {
long startTs = System.currentTimeMillis(); long startTs = System.currentTimeMillis();
liteNodeParser.parseBsqBlock(bsqBlock); liteNodeParser.parseBsqBlock(bsqBlock);
log.info("parseBlocks took {} ms", System.currentTimeMillis() - startTs); log.info("parseBlocks took {} ms", System.currentTimeMillis() - startTs);
bsqBlockChain.addBlock(bsqBlock);
return null; return null;
}); });

View file

@ -17,7 +17,7 @@
package io.bisq.core.dao.node.lite; package io.bisq.core.dao.node.lite;
import io.bisq.core.dao.blockchain.WriteModel; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException; import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException;
import io.bisq.core.dao.blockchain.vo.BsqBlock; import io.bisq.core.dao.blockchain.vo.BsqBlock;
import io.bisq.core.dao.blockchain.vo.Tx; import io.bisq.core.dao.blockchain.vo.Tx;
@ -40,10 +40,10 @@ import java.util.function.Consumer;
public class LiteNodeParser extends BsqParser { public class LiteNodeParser extends BsqParser {
@Inject @Inject
public LiteNodeParser(WriteModel writeModel, public LiteNodeParser(BsqBlockChain bsqBlockChain,
GenesisTxVerification genesisTxVerification, GenesisTxVerification genesisTxVerification,
BsqTxVerification bsqTxVerification) { BsqTxVerification bsqTxVerification) {
super(writeModel, genesisTxVerification, bsqTxVerification); super(bsqBlockChain, genesisTxVerification, bsqTxVerification);
} }
void parseBsqBlocks(List<BsqBlock> bsqBlocks, void parseBsqBlocks(List<BsqBlock> bsqBlocks,
@ -51,17 +51,17 @@ public class LiteNodeParser extends BsqParser {
throws BlockNotConnectingException { throws BlockNotConnectingException {
for (BsqBlock bsqBlock : bsqBlocks) { for (BsqBlock bsqBlock : bsqBlocks) {
parseBsqBlock(bsqBlock); parseBsqBlock(bsqBlock);
bsqBlockChain.addBlock(bsqBlock);
newBlockHandler.accept(bsqBlock); newBlockHandler.accept(bsqBlock);
} }
} }
void parseBsqBlock(BsqBlock bsqBlock) throws BlockNotConnectingException { void parseBsqBlock(BsqBlock bsqBlock) {
int blockHeight = bsqBlock.getHeight(); int blockHeight = bsqBlock.getHeight();
log.info("Parse block at height={} ", blockHeight); log.info("Parse block at height={} ", blockHeight);
List<Tx> txList = new ArrayList<>(bsqBlock.getTxs()); List<Tx> txList = new ArrayList<>(bsqBlock.getTxs());
List<Tx> bsqTxsInBlock = new ArrayList<>(); List<Tx> bsqTxsInBlock = new ArrayList<>();
bsqBlock.getTxs().forEach(tx -> checkForGenesisTx(blockHeight, bsqTxsInBlock, tx)); bsqBlock.getTxs().forEach(tx -> checkForGenesisTx(blockHeight, bsqTxsInBlock, tx));
recursiveFindBsqTxs(bsqTxsInBlock, txList, blockHeight, 0, 5300); recursiveFindBsqTxs(bsqTxsInBlock, txList, blockHeight, 0, 5300);
writeModel.addBlock(bsqBlock);
} }
} }

View file

@ -31,9 +31,9 @@ import io.bisq.core.btc.exceptions.WalletException;
import io.bisq.core.btc.wallet.BsqWalletService; import io.bisq.core.btc.wallet.BsqWalletService;
import io.bisq.core.btc.wallet.BtcWalletService; import io.bisq.core.btc.wallet.BtcWalletService;
import io.bisq.core.dao.DaoPeriodService; import io.bisq.core.dao.DaoPeriodService;
import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.BsqBlockChainChangeDispatcher; import io.bisq.core.dao.blockchain.BsqBlockChainChangeDispatcher;
import io.bisq.core.dao.blockchain.BsqBlockChainListener; import io.bisq.core.dao.blockchain.BsqBlockChainListener;
import io.bisq.core.dao.blockchain.ReadModel;
import io.bisq.core.dao.request.compensation.consensus.OpReturnData; import io.bisq.core.dao.request.compensation.consensus.OpReturnData;
import io.bisq.core.dao.request.compensation.consensus.Restrictions; import io.bisq.core.dao.request.compensation.consensus.Restrictions;
import io.bisq.core.provider.fee.FeeService; import io.bisq.core.provider.fee.FeeService;
@ -68,7 +68,7 @@ public class CompensationRequestManager implements PersistedDataHost, BsqBlockCh
private final DaoPeriodService daoPeriodService; private final DaoPeriodService daoPeriodService;
private final BsqWalletService bsqWalletService; private final BsqWalletService bsqWalletService;
private final BtcWalletService btcWalletService; private final BtcWalletService btcWalletService;
private final ReadModel readModel; private final BsqBlockChain bsqBlockChain;
private final Storage<CompensationRequestList> compensationRequestsStorage; private final Storage<CompensationRequestList> compensationRequestsStorage;
private final PublicKey signaturePubKey; private final PublicKey signaturePubKey;
private final FeeService feeService; private final FeeService feeService;
@ -90,7 +90,7 @@ public class CompensationRequestManager implements PersistedDataHost, BsqBlockCh
BsqWalletService bsqWalletService, BsqWalletService bsqWalletService,
BtcWalletService btcWalletService, BtcWalletService btcWalletService,
DaoPeriodService daoPeriodService, DaoPeriodService daoPeriodService,
ReadModel readModel, BsqBlockChain bsqBlockChain,
BsqBlockChainChangeDispatcher bsqBlockChainChangeDispatcher, BsqBlockChainChangeDispatcher bsqBlockChainChangeDispatcher,
KeyRing keyRing, KeyRing keyRing,
Storage<CompensationRequestList> compensationRequestsStorage, Storage<CompensationRequestList> compensationRequestsStorage,
@ -99,7 +99,7 @@ public class CompensationRequestManager implements PersistedDataHost, BsqBlockCh
this.bsqWalletService = bsqWalletService; this.bsqWalletService = bsqWalletService;
this.btcWalletService = btcWalletService; this.btcWalletService = btcWalletService;
this.daoPeriodService = daoPeriodService; this.daoPeriodService = daoPeriodService;
this.readModel = readModel; this.bsqBlockChain = bsqBlockChain;
this.compensationRequestsStorage = compensationRequestsStorage; this.compensationRequestsStorage = compensationRequestsStorage;
this.feeService = feeService; this.feeService = feeService;
@ -235,7 +235,7 @@ public class CompensationRequestManager implements PersistedDataHost, BsqBlockCh
} }
private boolean isInPhaseOrUnconfirmed(CompensationRequestPayload payload) { private boolean isInPhaseOrUnconfirmed(CompensationRequestPayload payload) {
return readModel.getTxMap().get(payload.getTxId()) == null || daoPeriodService.isTxInPhase(payload.getTxId(), DaoPeriodService.Phase.COMPENSATION_REQUESTS); return bsqBlockChain.getTxMap().get(payload.getTxId()) == null || daoPeriodService.isTxInPhase(payload.getTxId(), DaoPeriodService.Phase.COMPENSATION_REQUESTS);
} }
public boolean isMine(CompensationRequest compensationRequest) { public boolean isMine(CompensationRequest compensationRequest) {
@ -336,7 +336,7 @@ public class CompensationRequestManager implements PersistedDataHost, BsqBlockCh
pastRequests.setPredicate(request -> daoPeriodService.isTxInPastCycle(request.getPayload().getTxId())); pastRequests.setPredicate(request -> daoPeriodService.isTxInPastCycle(request.getPayload().getTxId()));
activeRequests.setPredicate(compensationRequest -> { activeRequests.setPredicate(compensationRequest -> {
return daoPeriodService.isTxInCurrentCycle(compensationRequest.getPayload().getTxId()) || return daoPeriodService.isTxInCurrentCycle(compensationRequest.getPayload().getTxId()) ||
(readModel.getTxMap().get(compensationRequest.getPayload().getTxId()) == null && (bsqBlockChain.getTxMap().get(compensationRequest.getPayload().getTxId()) == null &&
isMine(compensationRequest)); isMine(compensationRequest));
}); });
} }

View file

@ -4,17 +4,16 @@ import com.neemre.btcdcli4j.core.BitcoindException;
import com.neemre.btcdcli4j.core.CommunicationException; import com.neemre.btcdcli4j.core.CommunicationException;
import com.neemre.btcdcli4j.core.domain.Block; import com.neemre.btcdcli4j.core.domain.Block;
import io.bisq.common.proto.persistable.PersistenceProtoResolver; import io.bisq.common.proto.persistable.PersistenceProtoResolver;
import io.bisq.core.dao.DaoOptionKeys;
import io.bisq.core.dao.blockchain.BsqBlockChain; import io.bisq.core.dao.blockchain.BsqBlockChain;
import io.bisq.core.dao.blockchain.ReadModel;
import io.bisq.core.dao.blockchain.WriteModel;
import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException; import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException;
import io.bisq.core.dao.blockchain.exceptions.BsqBlockchainException; import io.bisq.core.dao.blockchain.exceptions.BsqBlockchainException;
import io.bisq.core.dao.blockchain.vo.Tx; import io.bisq.core.dao.blockchain.vo.Tx;
import io.bisq.core.dao.blockchain.vo.TxInput; import io.bisq.core.dao.blockchain.vo.TxInput;
import io.bisq.core.dao.blockchain.vo.TxOutput; import io.bisq.core.dao.blockchain.vo.TxOutput;
import io.bisq.core.dao.blockchain.vo.util.TxIdIndexTuple; import io.bisq.core.dao.blockchain.vo.util.TxIdIndexTuple;
import io.bisq.core.dao.node.consensus.*; import io.bisq.core.dao.node.consensus.BsqTxVerification;
import io.bisq.core.dao.node.consensus.IssuanceVerification;
import io.bisq.core.dao.node.consensus.OpReturnVerification;
import io.bisq.core.dao.node.full.rpc.RpcService; import io.bisq.core.dao.node.full.rpc.RpcService;
import mockit.Expectations; import mockit.Expectations;
import mockit.Injectable; import mockit.Injectable;
@ -24,7 +23,6 @@ import org.bitcoinj.core.Coin;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import javax.inject.Named;
import java.io.File; import java.io.File;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
@ -35,49 +33,31 @@ import static java.util.Arrays.asList;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
// Intro to jmockit can be found at http://jmockit.github.io/tutorial/Mocking.html
@RunWith(JMockit.class) @RunWith(JMockit.class)
public class FullNodeParserTest { public class FullNodeParserTest {
// @Tested classes are instantiated automatically when needed in a test case, @Tested(availableDuringSetup = true)
// using injection where possible, see http://jmockit.github.io/tutorial/Mocking.html#tested BsqBlockChain bsqBlockChain;
// To force instantiate earlier, use availableDuringSetup
@Tested(fullyInitialized = true, availableDuringSetup = true) @Tested(fullyInitialized = true, availableDuringSetup = true)
FullNodeParser fullNodeParser; FullNodeParser fullNodeParser;
@Tested(fullyInitialized = true, availableDuringSetup = true) @Tested(fullyInitialized = true, availableDuringSetup = true)
BsqBlockChain bsqBlockChain; BsqTxVerification bsqTxVerification;
@Tested(availableDuringSetup = true)
ReadModel readModel;
// Used by bsqTxVerification
@Tested(fullyInitialized = true, availableDuringSetup = true)
TxInputsVerification txInputsVerification;
@Tested(fullyInitialized = true, availableDuringSetup = true)
TxOutputsVerification txOutputsVerification;
// @Injectable are mocked resources used to for injecting into @Tested classes
// The naming of these resources doesn't matter, any resource that fits will be used for injection
// Used by bsqBlockChain
@Injectable @Injectable
PersistenceProtoResolver persistenceProtoResolver; PersistenceProtoResolver persistenceProtoResolver;
@Injectable @Injectable
File storageDir; File storageDir;
@Injectable @Injectable
String genesisTxId = "genesisTxId"; String genesisId = "genesisId";
@Injectable @Injectable
int genesisBlockHeight = 200; int genesisBlockHeight = 200;
// Used by fullNodeParser
@Injectable @Injectable
RpcService rpcService; RpcService rpcService;
@Tested(fullyInitialized = true, availableDuringSetup = true) @Injectable
WriteModel writeModel; OpReturnVerification opReturnVerification;
@Tested(fullyInitialized = true, availableDuringSetup = true) @Injectable
GenesisTxVerification genesisTxVerification; IssuanceVerification issuanceVerification;
@Tested(fullyInitialized = true, availableDuringSetup = true)
BsqTxVerification bsqTxVerification;
@Test @Test
public void testIsBsqTx() { public void testIsBsqTx() {
@ -94,18 +74,13 @@ public class FullNodeParserTest {
// 1) - null, 0 -> not BSQ transaction // 1) - null, 0 -> not BSQ transaction
// 2) - 100, null -> BSQ transaction // 2) - 100, null -> BSQ transaction
// 3) - 0, 100 -> BSQ transaction // 3) - 0, 100 -> BSQ transaction
new Expectations(readModel) {{ new Expectations(bsqBlockChain) {{
// Expectations can be recorded on mocked instances, either with specific matching arguments or catch all bsqBlockChain.getSpendableTxOutput(new TxIdIndexTuple("tx1", 0));
// http://jmockit.github.io/tutorial/Mocking.html#results
// Results are returned in the order they're recorded, so in this case for the first call to
// getSpendableTxOutput("tx1", 0) the return value will be Optional.empty()
// for the second call the return is Optional.of(new TxOutput(0,... and so on
readModel.getSpendableTxOutput(new TxIdIndexTuple("tx1", 0));
result = Optional.empty(); result = Optional.empty();
result = Optional.of(new TxOutput(0, 100, "txout1", null, null, null, height)); result = Optional.of(new TxOutput(0, 100, "txout1", null, null, null, height));
result = Optional.of(new TxOutput(0, 0, "txout1", null, null, null, height)); result = Optional.of(new TxOutput(0, 0, "txout1", null, null, null, height));
readModel.getSpendableTxOutput(new TxIdIndexTuple("tx1", 1)); bsqBlockChain.getSpendableTxOutput(new TxIdIndexTuple("tx1", 1));
result = Optional.of(new TxOutput(0, 0, "txout2", null, null, null, height)); result = Optional.of(new TxOutput(0, 0, "txout2", null, null, null, height));
result = Optional.empty(); result = Optional.empty();
result = Optional.of(new TxOutput(0, 100, "txout2", null, null, null, height)); result = Optional.of(new TxOutput(0, 100, "txout2", null, null, null, height));
@ -147,10 +122,10 @@ public class FullNodeParserTest {
Tx cbTx200 = new Tx(cbId200, 200, bh200, time, Tx cbTx200 = new Tx(cbId200, 200, bh200, time,
new ArrayList<TxInput>(), new ArrayList<TxInput>(),
asList(new TxOutput(0, 25, cbId200, null, null, null, 200))); asList(new TxOutput(0, 25, cbId200, null, null, null, 200)));
Tx genesisTx = new Tx(genesisTxId, 200, bh200, time, Tx genesisTx = new Tx(genesisId, 200, bh200, time,
asList(new TxInput("someoldtx", 0)), asList(new TxInput("someoldtx", 0)),
asList(new TxOutput(0, issuance.getValue(), genesisTxId, null, null, null, 200))); asList(new TxOutput(0, issuance.getValue(), genesisId, null, null, null, 200)));
Block block200 = new Block(bh200, 10, 10, 200, 2, "root", asList(cbId200, genesisTxId), time, Long.parseLong("1234"), "bits", BigDecimal.valueOf(1), "chainwork", bh199, bh201); Block block200 = new Block(bh200, 10, 10, 200, 2, "root", asList(cbId200, genesisId), time, Long.parseLong("1234"), "bits", BigDecimal.valueOf(1), "chainwork", bh199, bh201);
// Block 201 // Block 201
// Make a bsq transaction // Make a bsq transaction
@ -162,7 +137,7 @@ public class FullNodeParserTest {
new ArrayList<TxInput>(), new ArrayList<TxInput>(),
asList(new TxOutput(0, 25, cbId201, null, null, null, 201))); asList(new TxOutput(0, 25, cbId201, null, null, null, 201)));
Tx bsqTx1 = new Tx(bsqTx1Id, 201, bh201, time, Tx bsqTx1 = new Tx(bsqTx1Id, 201, bh201, time,
asList(new TxInput(genesisTxId, 0)), asList(new TxInput(genesisId, 0)),
asList(new TxOutput(0, bsqTx1Value1, bsqTx1Id, null, null, null, 201), asList(new TxOutput(0, bsqTx1Value1, bsqTx1Id, null, null, null, 201),
new TxOutput(1, bsqTx1Value2, bsqTx1Id, null, null, null, 201))); new TxOutput(1, bsqTx1Value2, bsqTx1Id, null, null, null, 201)));
Block block201 = new Block(bh201, 10, 10, 201, 2, "root", asList(cbId201, bsqTx1Id), time, Long.parseLong("1234"), "bits", BigDecimal.valueOf(1), "chainwork", bh200, "nextBlockHash"); Block block201 = new Block(bh201, 10, 10, 201, 2, "root", asList(cbId201, bsqTx1Id), time, Long.parseLong("1234"), "bits", BigDecimal.valueOf(1), "chainwork", bh200, "nextBlockHash");
@ -179,7 +154,7 @@ public class FullNodeParserTest {
result = cbTx199; result = cbTx199;
rpcService.requestTx(cbId200, genesisHeight); rpcService.requestTx(cbId200, genesisHeight);
result = cbTx200; result = cbTx200;
rpcService.requestTx(genesisTxId, genesisHeight); rpcService.requestTx(genesisId, genesisHeight);
result = genesisTx; result = genesisTx;
rpcService.requestTx(cbId201, 201); rpcService.requestTx(cbId201, 201);
result = cbTx201; result = cbTx201;
@ -192,25 +167,25 @@ public class FullNodeParserTest {
}); });
// Verify that the genesis tx has been added to the bsq blockchain with the correct issuance amount // Verify that the genesis tx has been added to the bsq blockchain with the correct issuance amount
assertTrue(readModel.getGenesisTx() == genesisTx); assertTrue(bsqBlockChain.getGenesisTx() == genesisTx);
assertTrue(readModel.getIssuedAmount().getValue() == issuance.getValue()); assertTrue(bsqBlockChain.getIssuedAmount().getValue() == issuance.getValue());
// And that other txs are not added // And that other txs are not added
assertFalse(readModel.containsTx(cbId199)); assertFalse(bsqBlockChain.containsTx(cbId199));
assertFalse(readModel.containsTx(cbId200)); assertFalse(bsqBlockChain.containsTx(cbId200));
assertFalse(readModel.containsTx(cbId201)); assertFalse(bsqBlockChain.containsTx(cbId201));
// But bsq txs are added // But bsq txs are added
assertTrue(readModel.containsTx(bsqTx1Id)); assertTrue(bsqBlockChain.containsTx(bsqTx1Id));
TxOutput bsqOut1 = readModel.getSpendableTxOutput(bsqTx1Id, 0).get(); TxOutput bsqOut1 = bsqBlockChain.getSpendableTxOutput(bsqTx1Id, 0).get();
assertTrue(bsqOut1.isUnspent()); assertTrue(bsqOut1.isUnspent());
assertTrue(bsqOut1.getValue() == bsqTx1Value1); assertTrue(bsqOut1.getValue() == bsqTx1Value1);
TxOutput bsqOut2 = readModel.getSpendableTxOutput(bsqTx1Id, 1).get(); TxOutput bsqOut2 = bsqBlockChain.getSpendableTxOutput(bsqTx1Id, 1).get();
assertTrue(bsqOut2.isUnspent()); assertTrue(bsqOut2.isUnspent());
assertTrue(bsqOut2.getValue() == bsqTx1Value2); assertTrue(bsqOut2.getValue() == bsqTx1Value2);
assertFalse(readModel.isTxOutputSpendable(genesisTxId, 0)); assertFalse(bsqBlockChain.isTxOutputSpendable(genesisId, 0));
assertTrue(readModel.isTxOutputSpendable(bsqTx1Id, 0)); assertTrue(bsqBlockChain.isTxOutputSpendable(bsqTx1Id, 0));
assertTrue(readModel.isTxOutputSpendable(bsqTx1Id, 1)); assertTrue(bsqBlockChain.isTxOutputSpendable(bsqTx1Id, 1));
} }
} }