use of bisq.core.dao.state.blockchain.SpentInfo in project bisq-core by bisq-network.
the class TxInputParser method process.
@SuppressWarnings("IfCanBeSwitch")
void process(TxOutputKey txOutputKey, int blockHeight, String txId, int inputIndex) {
bsqStateService.getUnspentTxOutput(txOutputKey).ifPresent(connectedTxOutput -> {
long inputValue = connectedTxOutput.getValue();
accumulatedInputValue += inputValue;
// If we are spending an output from a blind vote tx marked as VOTE_STAKE_OUTPUT we save it in our parsingModel
// for later verification at the outputs of a reveal tx.
TxOutputType connectedTxOutputType = connectedTxOutput.getTxOutputType();
switch(connectedTxOutputType) {
case UNDEFINED:
case GENESIS_OUTPUT:
case BSQ_OUTPUT:
case BTC_OUTPUT:
case PROPOSAL_OP_RETURN_OUTPUT:
case COMP_REQ_OP_RETURN_OUTPUT:
case CONFISCATE_BOND_OP_RETURN_OUTPUT:
case ISSUANCE_CANDIDATE_OUTPUT:
break;
case BLIND_VOTE_LOCK_STAKE_OUTPUT:
if (voteRevealInputState == TxInputParser.VoteRevealInputState.UNKNOWN) {
// The connected tx output of the blind vote tx is our input for the reveal tx.
// We allow only one input from any blind vote tx otherwise the vote reveal tx is invalid.
voteRevealInputState = TxInputParser.VoteRevealInputState.VALID;
} else {
log.warn("We have a tx which has >1 connected txOutputs marked as BLIND_VOTE_LOCK_STAKE_OUTPUT. " + "This is not a valid BSQ tx.");
voteRevealInputState = TxInputParser.VoteRevealInputState.INVALID;
}
break;
case BLIND_VOTE_OP_RETURN_OUTPUT:
case VOTE_REVEAL_UNLOCK_STAKE_OUTPUT:
case VOTE_REVEAL_OP_RETURN_OUTPUT:
break;
case LOCKUP:
// txOutput. The UNLOCK can only be spent after lockTime blocks has passed.
if (!optionalSpentLockupTxOutput.isPresent()) {
optionalSpentLockupTxOutput = Optional.of(connectedTxOutput);
unlockBlockHeight = blockHeight + connectedTxOutput.getLockTime();
}
break;
case LOCKUP_OP_RETURN_OUTPUT:
break;
case UNLOCK:
// This txInput is Spending an UNLOCK txOutput
spentUnlockConnectedTxOutputs.add(connectedTxOutput);
// TODO We should add unlockBlockHeight to TempTxOutput and remove unlockBlockHeight from tempTx
// then we can use connectedTxOutput to access the unlockBlockHeight instead of the tx
bsqStateService.getTx(connectedTxOutput.getTxId()).ifPresent(unlockTx -> {
// Only count the input as BSQ input if spent after unlock time
if (blockHeight < unlockTx.getUnlockBlockHeight()) {
accumulatedInputValue -= inputValue;
burntBondValue += inputValue;
}
});
break;
case INVALID_OUTPUT:
default:
break;
}
bsqStateService.setSpentInfo(connectedTxOutput.getKey(), new SpentInfo(blockHeight, txId, inputIndex));
bsqStateService.removeUnspentTxOutput(connectedTxOutput);
});
}
use of bisq.core.dao.state.blockchain.SpentInfo in project bisq-core by bisq-network.
the class JsonBlockChainExporter method maybeExport.
public void maybeExport() {
if (dumpBlockchainData) {
ListenableFuture<Void> future = executor.submit(() -> {
final BsqState bsqStateClone = bsqStateService.getClone();
Map<String, Tx> txMap = bsqStateService.getBlocksFromState(bsqStateClone).stream().filter(Objects::nonNull).flatMap(block -> block.getTxs().stream()).collect(Collectors.toMap(Tx::getId, tx -> tx));
for (Tx tx : txMap.values()) {
String txId = tx.getId();
final Optional<TxType> optionalTxType = bsqStateService.getOptionalTxType(txId);
optionalTxType.ifPresent(txType1 -> {
JsonTxType txType = txType1 != TxType.UNDEFINED_TX_TYPE ? JsonTxType.valueOf(txType1.name()) : null;
List<JsonTxOutput> outputs = new ArrayList<>();
tx.getTxOutputs().forEach(txOutput -> {
final Optional<SpentInfo> optionalSpentInfo = bsqStateService.getSpentInfo(txOutput);
final boolean isBsqOutput = bsqStateService.isBsqTxOutputType(txOutput);
final PubKeyScript pubKeyScript = txOutput.getPubKeyScript();
final JsonTxOutput outputForJson = new JsonTxOutput(txId, txOutput.getIndex(), isBsqOutput ? txOutput.getValue() : 0, !isBsqOutput ? txOutput.getValue() : 0, txOutput.getBlockHeight(), isBsqOutput, bsqStateService.getBurntFee(tx.getId()), txOutput.getAddress(), pubKeyScript != null ? new JsonScriptPubKey(pubKeyScript) : null, optionalSpentInfo.map(JsonSpentInfo::new).orElse(null), tx.getTime(), txType, txType != null ? txType.getDisplayString() : "", txOutput.getOpReturnData() != null ? Utils.HEX.encode(txOutput.getOpReturnData()) : null);
outputs.add(outputForJson);
txOutputFileManager.writeToDisc(Utilities.objectToJson(outputForJson), outputForJson.getId());
});
List<JsonTxInput> inputs = tx.getTxInputs().stream().map(txInput -> {
Optional<TxOutput> optionalTxOutput = bsqStateService.getConnectedTxOutput(txInput);
if (optionalTxOutput.isPresent()) {
final TxOutput connectedTxOutput = optionalTxOutput.get();
final boolean isBsqOutput = bsqStateService.isBsqTxOutputType(connectedTxOutput);
return new JsonTxInput(txInput.getConnectedTxOutputIndex(), txInput.getConnectedTxOutputTxId(), connectedTxOutput.getValue(), isBsqOutput, connectedTxOutput.getAddress(), tx.getTime());
} else {
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
final JsonTx jsonTx = new JsonTx(txId, tx.getBlockHeight(), tx.getBlockHash(), tx.getTime(), inputs, outputs, txType, txType != null ? txType.getDisplayString() : "", bsqStateService.getBurntFee(tx.getId()));
txFileManager.writeToDisc(Utilities.objectToJson(jsonTx), txId);
});
}
jsonFileManager.writeToDisc(Utilities.objectToJson(bsqStateClone), "BsqStateService");
return null;
});
Futures.addCallback(future, new FutureCallback<Void>() {
public void onSuccess(Void ignore) {
log.trace("onSuccess");
}
public void onFailure(@NotNull Throwable throwable) {
log.error(throwable.toString());
throwable.printStackTrace();
}
});
}
}
Aggregations