use of bisq.core.dao.state.blockchain.Tx 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();
}
});
}
}
use of bisq.core.dao.state.blockchain.Tx in project bisq-core by bisq-network.
the class BlockParser method parseBlock.
// /////////////////////////////////////////////////////////////////////////////////////////
// API
// /////////////////////////////////////////////////////////////////////////////////////////
/**
* @param rawBlock Contains all transactions of a bitcoin block without any BSQ specific data
* @return Block: Gets created from the rawBlock but contains only BSQ specific transactions.
* @throws BlockNotConnectingException If new block does not connect to previous block
*/
public Block parseBlock(RawBlock rawBlock) throws BlockNotConnectingException {
int blockHeight = rawBlock.getHeight();
log.debug("Parse block at height={} ", blockHeight);
validateIfBlockIsConnecting(rawBlock);
bsqStateService.onNewBlockHeight(blockHeight);
// We create a block from the rawBlock but the transaction list is not set yet (is empty)
final Block block = new Block(blockHeight, rawBlock.getTime(), rawBlock.getHash(), rawBlock.getPreviousBlockHash());
if (isBlockAlreadyAdded(rawBlock)) {
// TODO check how/if that can happen
log.warn("Block was already added.");
DevEnv.logErrorAndThrowIfDevMode("Block was already added. rawBlock=" + rawBlock);
} else {
bsqStateService.onNewBlockWithEmptyTxs(block);
}
// Worst case is that all txs in a block are depending on another, so only one get resolved at each iteration.
// Min tx size is 189 bytes (normally about 240 bytes), 1 MB can contain max. about 5300 txs (usually 2000).
// Realistically we don't expect more then a few recursive calls.
// There are some blocks with testing such dependency chains like block 130768 where at each iteration only
// one get resolved.
// Lately there is a patter with 24 iterations observed
long startTs = System.currentTimeMillis();
List<Tx> txList = block.getTxs();
rawBlock.getRawTxs().forEach(rawTx -> txParser.findTx(rawTx, genesisTxId, genesisBlockHeight, genesisTotalSupply).ifPresent(txList::add));
log.debug("parseBsqTxs took {} ms", rawBlock.getRawTxs().size(), System.currentTimeMillis() - startTs);
bsqStateService.onParseBlockComplete(block);
return block;
}
use of bisq.core.dao.state.blockchain.Tx in project bisq-core by bisq-network.
the class IssuanceService method issueBsq.
public void issueBsq(CompensationProposal compensationProposal, int chainHeight) {
bsqStateService.getIssuanceCandidateTxOutputs().stream().filter(txOutput -> isValid(txOutput, compensationProposal, periodService, chainHeight)).forEach(txOutput -> {
// We don't check atm if the output is unspent. We cannot use the bsqWallet as that would not
// reflect our current block state (could have been spent at later block which is valid and
// bsqWallet would show that spent state). We would need to support a spent status for the outputs
// which are interpreted as BTC (as a not yet accepted comp. request).
Optional<Tx> optionalTx = bsqStateService.getTx(compensationProposal.getTxId());
if (optionalTx.isPresent()) {
long amount = compensationProposal.getRequestedBsq().value;
Tx tx = optionalTx.get();
// We use key from first input
TxInput txInput = tx.getTxInputs().get(0);
String pubKey = txInput.getPubKey();
Issuance issuance = new Issuance(tx.getId(), chainHeight, amount, pubKey);
bsqStateService.addIssuance(issuance);
bsqStateService.addUnspentTxOutput(txOutput);
StringBuilder sb = new StringBuilder();
sb.append("\n################################################################################\n");
sb.append("We issued new BSQ to tx with ID ").append(txOutput.getTxId()).append("\nfor compensationProposal with UID ").append(compensationProposal.getTxId()).append("\n################################################################################\n");
log.info(sb.toString());
} else {
// TODO throw exception
log.error("Tx for compensation request not found. txId={}", compensationProposal.getTxId());
}
});
}
Aggregations