use of bisq.core.dao.blockchain.vo.TxOutput in project bisq-core by bisq-network.
the class JsonBlockChainExporter method maybeExport.
public void maybeExport() {
if (dumpBlockchainData) {
ListenableFuture<Void> future = executor.submit(() -> {
final BsqBlockChain bsqBlockChainClone = readableBsqBlockChain.getClone();
for (Tx tx : bsqBlockChainClone.getTxMap().values()) {
String txId = tx.getId();
JsonTxType txType = tx.getTxType() != TxType.UNDEFINED_TX_TYPE ? JsonTxType.valueOf(tx.getTxType().name()) : null;
List<JsonTxOutput> outputs = new ArrayList<>();
tx.getOutputs().stream().forEach(txOutput -> {
final JsonTxOutput outputForJson = new JsonTxOutput(txId, txOutput.getIndex(), txOutput.isVerified() ? txOutput.getValue() : 0, !txOutput.isVerified() ? txOutput.getValue() : 0, txOutput.getBlockHeight(), txOutput.isVerified(), tx.getBurntFee(), txOutput.getAddress(), new JsonScriptPubKey(txOutput.getPubKeyScript()), txOutput.getSpentInfo() != null ? new JsonSpentInfo(txOutput.getSpentInfo()) : 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.getInputs().stream().map(txInput -> {
final TxOutput connectedTxOutput = txInput.getConnectedTxOutput();
return new JsonTxInput(txInput.getConnectedTxOutputIndex(), txInput.getConnectedTxOutputTxId(), connectedTxOutput != null ? connectedTxOutput.getValue() : 0, connectedTxOutput != null && connectedTxOutput.isVerified(), connectedTxOutput != null ? connectedTxOutput.getAddress() : null, tx.getTime());
}).collect(Collectors.toList());
final JsonTx jsonTx = new JsonTx(txId, tx.getBlockHeight(), tx.getBlockHash(), tx.getTime(), inputs, outputs, txType, txType != null ? txType.getDisplayString() : "", tx.getBurntFee());
txFileManager.writeToDisc(Utilities.objectToJson(jsonTx), txId);
}
bsqBlockChainFileManager.writeToDisc(Utilities.objectToJson(bsqBlockChainClone), "BsqBlockChain");
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();
}
});
}
}
use of bisq.core.dao.blockchain.vo.TxOutput in project bisq-core by bisq-network.
the class BsqTxController method getTxTypeForOpReturn.
@NotNull
private TxType getTxTypeForOpReturn(Tx tx, OpReturnType opReturnType) {
TxType txType;
switch(opReturnType) {
case COMPENSATION_REQUEST:
checkArgument(tx.getOutputs().size() >= 3, "Compensation request tx need to have at least 3 outputs");
final TxOutput issuanceTxOutput = tx.getOutputs().get(1);
checkArgument(issuanceTxOutput.getTxOutputType() == TxOutputType.ISSUANCE_CANDIDATE_OUTPUT, "Compensation request txOutput type need to be COMPENSATION_REQUEST_ISSUANCE_CANDIDATE_OUTPUT");
// second output is issuance candidate
if (issuanceTxOutput.isVerified()) {
// TODO can that even happen as the voting will be applied later then the parsing of the tx
// If he have the issuance candidate already accepted by voting it gets the verified flag set
txType = TxType.ISSUANCE;
} else {
// Otherwise we have an open or rejected compensation request
txType = TxType.COMPENSATION_REQUEST;
}
break;
case PROPOSAL:
txType = TxType.PROPOSAL;
break;
case BLIND_VOTE:
txType = TxType.BLIND_VOTE;
break;
case VOTE_REVEAL:
txType = TxType.VOTE_REVEAL;
break;
case LOCK_UP:
// TODO
txType = TxType.LOCK_UP;
break;
case UNLOCK:
// TODO
txType = TxType.UN_LOCK;
break;
default:
log.warn("We got a BSQ tx with fee and unknown OP_RETURN. tx={}", tx);
txType = TxType.INVALID;
}
return txType;
}
use of bisq.core.dao.blockchain.vo.TxOutput in project bisq-core by bisq-network.
the class RpcService method requestTx.
public Tx requestTx(String txId, int blockHeight) throws BsqBlockchainException {
try {
RawTransaction rawTransaction = requestRawTransaction(txId);
// rawTransaction.getTime() is in seconds but we keep it in ms internally
final long time = rawTransaction.getTime() * 1000;
final List<TxInput> txInputs = rawTransaction.getVIn().stream().filter(rawInput -> rawInput != null && rawInput.getVOut() != null && rawInput.getTxId() != null).map(rawInput -> new TxInput(rawInput.getTxId(), rawInput.getVOut())).collect(Collectors.toList());
final List<TxOutput> txOutputs = rawTransaction.getVOut().stream().filter(e -> e != null && e.getN() != null && e.getValue() != null && e.getScriptPubKey() != null).map(rawOutput -> {
byte[] opReturnData = null;
final com.neemre.btcdcli4j.core.domain.PubKeyScript scriptPubKey = rawOutput.getScriptPubKey();
if (scriptPubKey.getType().equals(ScriptTypes.NULL_DATA)) {
String[] chunks = scriptPubKey.getAsm().split(" ");
// We get on testnet a lot of "OP_RETURN 0" data, so we filter those away
if (chunks.length == 2 && chunks[0].equals("OP_RETURN") && !"0".equals(chunks[1])) {
try {
opReturnData = Utils.HEX.decode(chunks[1]);
} catch (Throwable t) {
// We get sometimes exceptions, seems BitcoinJ
// cannot handle all existing OP_RETURN data, but we ignore them
// anyway as our OP_RETURN data is valid in BitcoinJ
log.warn("Error at Utils.HEX.decode(chunks[1]): " + t.toString() + " / chunks[1]=" + chunks[1]);
}
}
}
// We don't support raw MS which are the only case where scriptPubKey.getAddresses()>1
String address = scriptPubKey.getAddresses() != null && scriptPubKey.getAddresses().size() == 1 ? scriptPubKey.getAddresses().get(0) : null;
final PubKeyScript pubKeyScript = dumpBlockchainData ? new PubKeyScript(scriptPubKey) : null;
return new TxOutput(rawOutput.getN(), rawOutput.getValue().movePointRight(8).longValue(), rawTransaction.getTxId(), pubKeyScript, address, opReturnData, blockHeight);
}).collect(Collectors.toList());
return new Tx(txId, blockHeight, rawTransaction.getBlockHash(), time, ImmutableList.copyOf(txInputs), ImmutableList.copyOf(txOutputs));
} catch (BitcoindException | CommunicationException e) {
log.error("error at requestTx with txId={}, blockHeight={}", txId, blockHeight);
throw new BsqBlockchainException(e.getMessage(), e);
}
}
use of bisq.core.dao.blockchain.vo.TxOutput in project bisq-core by bisq-network.
the class VoteService method revealVote.
private void revealVote(MyVote myVote) {
byte[] hashOfBlindVoteList = VoteConsensus.getHashOfBlindVoteList(blindVoteSortedList);
log.info("Sha256Ripemd160 hash of hashOfBlindVoteList " + Utilities.bytesAsHexString(hashOfBlindVoteList));
byte[] opReturnData = VoteConsensus.getOpReturnDataForVoteReveal(hashOfBlindVoteList, myVote.getSecretKey());
final Set<TxOutput> lockedForVoteTxOutputs = readableBsqBlockChain.getLockedForVoteTxOutputs();
Optional<TxOutput> optionalStakeTxOutput = lockedForVoteTxOutputs.stream().filter(txOutput -> txOutput.getTxId().equals(myVote.getTxId())).findAny();
if (optionalStakeTxOutput.isPresent()) {
try {
final TxOutput stakeTxOutput = optionalStakeTxOutput.get();
VoteConsensus.unlockStakeTxOutputType(stakeTxOutput);
Transaction voteRevealTx = getVoteRevealTx(stakeTxOutput, opReturnData);
myVote.setRevealTxId(voteRevealTx.getHashAsString());
myVoteListStorage.queueUpForSave();
publishRevealTx(voteRevealTx, new FutureCallback<Transaction>() {
@Override
public void onSuccess(@Nullable Transaction result) {
}
@Override
public void onFailure(@NotNull Throwable t) {
}
});
} catch (InsufficientMoneyException e) {
e.printStackTrace();
} catch (WalletException e) {
e.printStackTrace();
} catch (TransactionVerificationException e) {
e.printStackTrace();
}
} else {
// log.warn("optionalStakeTxOutput is not present. myVote={}", myVote);
}
}
use of bisq.core.dao.blockchain.vo.TxOutput in project bisq-desktop by bisq-network.
the class BsqTxView method getCompensationRequestTxListItems.
// We add manually a modified copy of the compensation request tx if it has become an issuance tx
// It is a bit weird to have one tx displayed 2 times but I think it is better to show both aspects
// separately. First the compensation request tx with the fee then after voting the issuance.
private List<BsqTxListItem> getCompensationRequestTxListItems(List<BsqTxListItem> items) {
List<BsqTxListItem> issuanceTxList = new ArrayList<>();
items.stream().filter(item -> item.getTxType() == TxType.COMPENSATION_REQUEST).peek(item -> {
final Tx tx = readableBsqBlockChain.getTx(item.getTxId()).get();
// We have mandatory BSQ change at output 0
long changeValue = tx.getOutputs().get(0).getValue();
long inputValue = tx.getInputs().stream().filter(input -> input.getConnectedTxOutput() != null).mapToLong(input -> input.getConnectedTxOutput().getValue()).sum();
// We want to show fee as negative number
long fee = changeValue - inputValue;
item.setAmount(Coin.valueOf(fee));
}).filter(item -> {
final Optional<Tx> optionalTx = readableBsqBlockChain.getTx(item.getTxId());
if (optionalTx.isPresent()) {
final List<TxOutput> outputs = optionalTx.get().getOutputs();
if (!outputs.isEmpty()) {
return outputs.get(0).getTxOutputType() == TxOutputType.BSQ_OUTPUT;
}
}
return false;
}).forEach(item -> {
final Tx tx = readableBsqBlockChain.getTx(item.getTxId()).get();
final int blockHeight = tx.getBlockHeight();
final int issuanceBlockHeight = daoPeriodService.getAbsoluteStartBlockOfPhase(blockHeight, DaoPeriodService.Phase.ISSUANCE);
// We use the time of the block height of the start of the issuance period
final long blockTimeInSec = readableBsqBlockChain.getBlockTime(issuanceBlockHeight);
final BsqTxListItem issuanceItem = new BsqTxListItem(item.getTransaction(), bsqWalletService, btcWalletService, Optional.of(TxType.ISSUANCE), item.isBurnedBsqTx(), new Date(blockTimeInSec * 1000), bsqFormatter);
// On output 1 we have the issuance candidate
long issuanceValue = tx.getOutputs().get(1).getValue();
issuanceItem.setAmount(Coin.valueOf(issuanceValue));
issuanceTxList.add(issuanceItem);
});
return issuanceTxList;
}
Aggregations