mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-20 10:22:18 +01:00
Merge pull request #1721 from ManfredKarrer/update-json-for-bsq-explorer
Update json for bsq explorer
This commit is contained in:
commit
b6a4e028c6
@ -53,7 +53,7 @@ import bisq.core.dao.node.BsqNodeProvider;
|
||||
import bisq.core.dao.node.full.FullNode;
|
||||
import bisq.core.dao.node.full.RpcService;
|
||||
import bisq.core.dao.node.full.network.FullNodeNetworkService;
|
||||
import bisq.core.dao.node.json.JsonBlockChainExporter;
|
||||
import bisq.core.dao.node.json.ExportJsonFilesService;
|
||||
import bisq.core.dao.node.lite.LiteNode;
|
||||
import bisq.core.dao.node.lite.network.LiteNodeNetworkService;
|
||||
import bisq.core.dao.node.parser.BlockParser;
|
||||
@ -99,7 +99,7 @@ public class DaoModule extends AppModule {
|
||||
bind(BsqState.class).in(Singleton.class);
|
||||
bind(BsqStateService.class).in(Singleton.class);
|
||||
bind(SnapshotManager.class).in(Singleton.class);
|
||||
bind(JsonBlockChainExporter.class).in(Singleton.class);
|
||||
bind(ExportJsonFilesService.class).in(Singleton.class);
|
||||
|
||||
// Period
|
||||
bind(CycleService.class).in(Singleton.class);
|
||||
|
@ -25,6 +25,7 @@ import bisq.core.dao.governance.voteresult.VoteResultService;
|
||||
import bisq.core.dao.governance.votereveal.VoteRevealService;
|
||||
import bisq.core.dao.node.BsqNode;
|
||||
import bisq.core.dao.node.BsqNodeProvider;
|
||||
import bisq.core.dao.node.json.ExportJsonFilesService;
|
||||
import bisq.core.dao.state.BsqStateService;
|
||||
import bisq.core.dao.state.period.CycleService;
|
||||
|
||||
@ -35,7 +36,6 @@ import com.google.inject.Inject;
|
||||
/**
|
||||
* High level entry point for Dao domain.
|
||||
* We initialize all main service classes here to be sure they are started.
|
||||
*
|
||||
*/
|
||||
public class DaoSetup {
|
||||
private final BsqStateService bsqStateService;
|
||||
@ -47,6 +47,7 @@ public class DaoSetup {
|
||||
private final VoteRevealService voteRevealService;
|
||||
private final VoteResultService voteResultService;
|
||||
private final BsqNode bsqNode;
|
||||
private final ExportJsonFilesService exportJsonFilesService;
|
||||
|
||||
@Inject
|
||||
public DaoSetup(BsqNodeProvider bsqNodeProvider,
|
||||
@ -57,7 +58,8 @@ public class DaoSetup {
|
||||
BlindVoteListService blindVoteListService,
|
||||
MyBlindVoteListService myBlindVoteListService,
|
||||
VoteRevealService voteRevealService,
|
||||
VoteResultService voteResultService) {
|
||||
VoteResultService voteResultService,
|
||||
ExportJsonFilesService exportJsonFilesService) {
|
||||
this.bsqStateService = bsqStateService;
|
||||
this.cycleService = cycleService;
|
||||
this.proposalService = proposalService;
|
||||
@ -66,6 +68,7 @@ public class DaoSetup {
|
||||
this.myBlindVoteListService = myBlindVoteListService;
|
||||
this.voteRevealService = voteRevealService;
|
||||
this.voteResultService = voteResultService;
|
||||
this.exportJsonFilesService = exportJsonFilesService;
|
||||
|
||||
bsqNode = bsqNodeProvider.getBsqNode();
|
||||
}
|
||||
@ -81,6 +84,7 @@ public class DaoSetup {
|
||||
myBlindVoteListService.addListeners();
|
||||
voteRevealService.addListeners();
|
||||
voteResultService.addListeners();
|
||||
exportJsonFilesService.addListeners();
|
||||
|
||||
bsqStateService.start();
|
||||
cycleService.start();
|
||||
@ -90,6 +94,7 @@ public class DaoSetup {
|
||||
myBlindVoteListService.start();
|
||||
voteRevealService.start();
|
||||
voteResultService.start();
|
||||
exportJsonFilesService.start();
|
||||
|
||||
bsqNode.setErrorMessageHandler(errorMessageHandler);
|
||||
bsqNode.start();
|
||||
|
@ -19,7 +19,7 @@ package bisq.core.dao.node.full;
|
||||
|
||||
import bisq.core.dao.node.BsqNode;
|
||||
import bisq.core.dao.node.full.network.FullNodeNetworkService;
|
||||
import bisq.core.dao.node.json.JsonBlockChainExporter;
|
||||
import bisq.core.dao.node.json.ExportJsonFilesService;
|
||||
import bisq.core.dao.node.parser.BlockParser;
|
||||
import bisq.core.dao.node.parser.exceptions.BlockNotConnectingException;
|
||||
import bisq.core.dao.state.BsqStateService;
|
||||
@ -49,7 +49,7 @@ public class FullNode extends BsqNode {
|
||||
|
||||
private final RpcService rpcService;
|
||||
private final FullNodeNetworkService fullNodeNetworkService;
|
||||
private final JsonBlockChainExporter jsonBlockChainExporter;
|
||||
private final ExportJsonFilesService exportJsonFilesService;
|
||||
private boolean addBlockHandlerAdded;
|
||||
|
||||
|
||||
@ -64,12 +64,12 @@ public class FullNode extends BsqNode {
|
||||
SnapshotManager snapshotManager,
|
||||
P2PService p2PService,
|
||||
RpcService rpcService,
|
||||
JsonBlockChainExporter jsonBlockChainExporter,
|
||||
ExportJsonFilesService exportJsonFilesService,
|
||||
FullNodeNetworkService fullNodeNetworkService) {
|
||||
super(blockParser, bsqStateService, snapshotManager, p2PService);
|
||||
this.rpcService = rpcService;
|
||||
|
||||
this.jsonBlockChainExporter = jsonBlockChainExporter;
|
||||
this.exportJsonFilesService = exportJsonFilesService;
|
||||
this.fullNodeNetworkService = fullNodeNetworkService;
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ public class FullNode extends BsqNode {
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
jsonBlockChainExporter.shutDown();
|
||||
exportJsonFilesService.shutDown();
|
||||
fullNodeNetworkService.shutDown();
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ public class FullNode extends BsqNode {
|
||||
}
|
||||
|
||||
private void onNewBlock(Block block) {
|
||||
jsonBlockChainExporter.maybeExport();
|
||||
exportJsonFilesService.exportToJson();
|
||||
|
||||
if (p2pNetworkReady && parseBlockchainComplete)
|
||||
fullNodeNetworkService.publishNewBlock(block);
|
||||
|
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 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 bisq.core.dao.node.json;
|
||||
|
||||
import bisq.core.dao.DaoOptionKeys;
|
||||
import bisq.core.dao.DaoSetupService;
|
||||
import bisq.core.dao.state.BsqState;
|
||||
import bisq.core.dao.state.BsqStateService;
|
||||
import bisq.core.dao.state.blockchain.PubKeyScript;
|
||||
import bisq.core.dao.state.blockchain.TxOutput;
|
||||
import bisq.core.dao.state.blockchain.TxType;
|
||||
|
||||
import bisq.common.storage.FileUtil;
|
||||
import bisq.common.storage.JsonFileManager;
|
||||
import bisq.common.storage.Storage;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import org.bitcoinj.core.Utils;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Slf4j
|
||||
public class ExportJsonFilesService implements DaoSetupService {
|
||||
private final BsqStateService bsqStateService;
|
||||
private final File storageDir;
|
||||
private final boolean dumpBlockchainData;
|
||||
|
||||
private final ListeningExecutorService executor = Utilities.getListeningExecutorService("JsonExporter",
|
||||
1, 1, 1200);
|
||||
private JsonFileManager txFileManager, txOutputFileManager, bsqStateFileManager;
|
||||
|
||||
@Inject
|
||||
public ExportJsonFilesService(BsqStateService bsqStateService,
|
||||
@Named(Storage.STORAGE_DIR) File storageDir,
|
||||
@Named(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA) boolean dumpBlockchainData) {
|
||||
this.bsqStateService = bsqStateService;
|
||||
this.storageDir = storageDir;
|
||||
this.dumpBlockchainData = dumpBlockchainData;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoSetupService
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void addListeners() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (dumpBlockchainData) {
|
||||
File jsonDir = new File(Paths.get(storageDir.getAbsolutePath(), "json").toString());
|
||||
File txDir = new File(Paths.get(storageDir.getAbsolutePath(), "json", "tx").toString());
|
||||
File txOutputDir = new File(Paths.get(storageDir.getAbsolutePath(), "json", "txo").toString());
|
||||
File bsqStateDir = new File(Paths.get(storageDir.getAbsolutePath(), "json", "all").toString());
|
||||
try {
|
||||
if (txDir.exists())
|
||||
FileUtil.deleteDirectory(txDir);
|
||||
if (txOutputDir.exists())
|
||||
FileUtil.deleteDirectory(txOutputDir);
|
||||
if (bsqStateDir.exists())
|
||||
FileUtil.deleteDirectory(bsqStateDir);
|
||||
if (jsonDir.exists())
|
||||
FileUtil.deleteDirectory(jsonDir);
|
||||
} catch (IOException e) {
|
||||
log.error(e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (!jsonDir.mkdir())
|
||||
log.warn("make jsonDir failed.\njsonDir=" + jsonDir.getAbsolutePath());
|
||||
|
||||
if (!txDir.mkdir())
|
||||
log.warn("make txDir failed.\ntxDir=" + txDir.getAbsolutePath());
|
||||
|
||||
if (!txOutputDir.mkdir())
|
||||
log.warn("make txOutputDir failed.\ntxOutputDir=" + txOutputDir.getAbsolutePath());
|
||||
|
||||
if (!bsqStateDir.mkdir())
|
||||
log.warn("make bsqStateDir failed.\nbsqStateDir=" + bsqStateDir.getAbsolutePath());
|
||||
|
||||
txFileManager = new JsonFileManager(txDir);
|
||||
txOutputFileManager = new JsonFileManager(txOutputDir);
|
||||
bsqStateFileManager = new JsonFileManager(bsqStateDir);
|
||||
}
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
if (dumpBlockchainData) {
|
||||
txFileManager.shutDown();
|
||||
txOutputFileManager.shutDown();
|
||||
bsqStateFileManager.shutDown();
|
||||
}
|
||||
}
|
||||
|
||||
public void exportToJson() {
|
||||
if (dumpBlockchainData) {
|
||||
// We store the data we need once we write the data to disk (in the thread) locally.
|
||||
// Access to bsqStateService is single threaded, we must not access bsqStateService from the thread.
|
||||
List<JsonTxOutput> allJsonTxOutputs = new ArrayList<>();
|
||||
List<JsonTx> jsonTxs = new ArrayList<>();
|
||||
BsqState bsqStateClone = bsqStateService.getClone();
|
||||
|
||||
bsqStateService.getTxStream().forEach(tx -> {
|
||||
List<JsonTxOutput> jsonTxOutputs = new ArrayList<>();
|
||||
String txId = tx.getId();
|
||||
long time = tx.getTime();
|
||||
int blockHeight = tx.getBlockHeight();
|
||||
long burntFee = bsqStateService.getBurntFee(tx.getId());
|
||||
TxType txType = tx.getTxType();
|
||||
JsonTxType jsonTxType = txType != null ? JsonTxType.valueOf(txType.name()) : null;
|
||||
String jsonTxTypeDisplayString = jsonTxType != null ? jsonTxType.getDisplayString() : "";
|
||||
tx.getTxOutputs().forEach(txOutput -> {
|
||||
boolean isBsqTxOutputType = bsqStateService.isBsqTxOutputType(txOutput);
|
||||
long bsqAmount = isBsqTxOutputType ? txOutput.getValue() : 0;
|
||||
long btcAmount = !isBsqTxOutputType ? txOutput.getValue() : 0;
|
||||
PubKeyScript pubKeyScript = txOutput.getPubKeyScript();
|
||||
JsonScriptPubKey scriptPubKey = pubKeyScript != null ? new JsonScriptPubKey(pubKeyScript) : null;
|
||||
JsonSpentInfo spentInfo = bsqStateService.getSpentInfo(txOutput).map(JsonSpentInfo::new).orElse(null);
|
||||
JsonTxOutputType txOutputType = JsonTxOutputType.valueOf(txOutput.getTxOutputType().name());
|
||||
int lockTime = txOutput.getLockTime();
|
||||
String opReturn = txOutput.getOpReturnData() != null ? Utils.HEX.encode(txOutput.getOpReturnData()) : null;
|
||||
JsonTxOutput jsonTxOutput = new JsonTxOutput(txId,
|
||||
txOutput.getIndex(),
|
||||
bsqAmount,
|
||||
btcAmount,
|
||||
blockHeight,
|
||||
isBsqTxOutputType,
|
||||
burntFee,
|
||||
txOutput.getAddress(),
|
||||
scriptPubKey,
|
||||
spentInfo,
|
||||
time,
|
||||
jsonTxType,
|
||||
jsonTxTypeDisplayString,
|
||||
txOutputType,
|
||||
txOutputType.getDisplayString(),
|
||||
opReturn,
|
||||
lockTime
|
||||
);
|
||||
jsonTxOutputs.add(jsonTxOutput);
|
||||
allJsonTxOutputs.add(jsonTxOutput);
|
||||
});
|
||||
|
||||
List<JsonTxInput> inputs = tx.getTxInputs().stream()
|
||||
.map(txInput -> {
|
||||
Optional<TxOutput> optionalTxOutput = bsqStateService.getConnectedTxOutput(txInput);
|
||||
if (optionalTxOutput.isPresent()) {
|
||||
TxOutput connectedTxOutput = optionalTxOutput.get();
|
||||
boolean isBsqTxOutputType = bsqStateService.isBsqTxOutputType(connectedTxOutput);
|
||||
return new JsonTxInput(txInput.getConnectedTxOutputIndex(),
|
||||
txInput.getConnectedTxOutputTxId(),
|
||||
connectedTxOutput.getValue(),
|
||||
isBsqTxOutputType,
|
||||
connectedTxOutput.getAddress(),
|
||||
time);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
JsonTx jsonTx = new JsonTx(txId,
|
||||
blockHeight,
|
||||
tx.getBlockHash(),
|
||||
time,
|
||||
inputs,
|
||||
jsonTxOutputs,
|
||||
jsonTxType,
|
||||
jsonTxTypeDisplayString,
|
||||
burntFee,
|
||||
tx.getUnlockBlockHeight());
|
||||
|
||||
jsonTxs.add(jsonTx);
|
||||
});
|
||||
|
||||
ListenableFuture<Void> future = executor.submit(() -> {
|
||||
bsqStateFileManager.writeToDisc(Utilities.objectToJson(bsqStateClone), "BsqStateService");
|
||||
allJsonTxOutputs.forEach(jsonTxOutput -> txOutputFileManager.writeToDisc(Utilities.objectToJson(jsonTxOutput), jsonTxOutput.getId()));
|
||||
jsonTxs.forEach(jsonTx -> txFileManager.writeToDisc(Utilities.objectToJson(jsonTx), jsonTx.getId()));
|
||||
return null;
|
||||
});
|
||||
|
||||
Futures.addCallback(future, new FutureCallback<>() {
|
||||
public void onSuccess(Void ignore) {
|
||||
log.trace("onSuccess");
|
||||
}
|
||||
|
||||
public void onFailure(@NotNull Throwable throwable) {
|
||||
log.error(throwable.toString());
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,206 +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 bisq.core.dao.node.json;
|
||||
|
||||
import bisq.core.dao.DaoOptionKeys;
|
||||
import bisq.core.dao.state.BsqState;
|
||||
import bisq.core.dao.state.BsqStateService;
|
||||
import bisq.core.dao.state.blockchain.PubKeyScript;
|
||||
import bisq.core.dao.state.blockchain.SpentInfo;
|
||||
import bisq.core.dao.state.blockchain.Tx;
|
||||
import bisq.core.dao.state.blockchain.TxOutput;
|
||||
import bisq.core.dao.state.blockchain.TxType;
|
||||
|
||||
import bisq.common.storage.FileUtil;
|
||||
import bisq.common.storage.JsonFileManager;
|
||||
import bisq.common.storage.Storage;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import org.bitcoinj.core.Utils;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Slf4j
|
||||
public class JsonBlockChainExporter {
|
||||
private final BsqStateService bsqStateService;
|
||||
private final boolean dumpBlockchainData;
|
||||
|
||||
private final ListeningExecutorService executor = Utilities.getListeningExecutorService("JsonExporter", 1, 1, 1200);
|
||||
private JsonFileManager txFileManager, txOutputFileManager, jsonFileManager;
|
||||
|
||||
@Inject
|
||||
public JsonBlockChainExporter(BsqStateService bsqStateService,
|
||||
@Named(Storage.STORAGE_DIR) File storageDir,
|
||||
@Named(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA) boolean dumpBlockchainData) {
|
||||
this.bsqStateService = bsqStateService;
|
||||
this.dumpBlockchainData = dumpBlockchainData;
|
||||
|
||||
init(storageDir, dumpBlockchainData);
|
||||
}
|
||||
|
||||
private void init(@Named(Storage.STORAGE_DIR) File storageDir, @Named(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA) boolean dumpBlockchainData) {
|
||||
if (dumpBlockchainData) {
|
||||
File txDir = new File(Paths.get(storageDir.getAbsolutePath(), "tx").toString());
|
||||
File txOutputDir = new File(Paths.get(storageDir.getAbsolutePath(), "txo").toString());
|
||||
File blockchainDir = new File(Paths.get(storageDir.getAbsolutePath(), "all").toString());
|
||||
try {
|
||||
if (txDir.exists())
|
||||
FileUtil.deleteDirectory(txDir);
|
||||
if (txOutputDir.exists())
|
||||
FileUtil.deleteDirectory(txOutputDir);
|
||||
if (blockchainDir.exists())
|
||||
FileUtil.deleteDirectory(blockchainDir);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (!txDir.mkdir())
|
||||
log.warn("make txDir failed.\ntxDir=" + txDir.getAbsolutePath());
|
||||
|
||||
if (!txOutputDir.mkdir())
|
||||
log.warn("make txOutputDir failed.\ntxOutputDir=" + txOutputDir.getAbsolutePath());
|
||||
|
||||
if (!blockchainDir.mkdir())
|
||||
log.warn("make blockchainDir failed.\nblockchainDir=" + blockchainDir.getAbsolutePath());
|
||||
|
||||
txFileManager = new JsonFileManager(txDir);
|
||||
txOutputFileManager = new JsonFileManager(txOutputDir);
|
||||
jsonFileManager = new JsonFileManager(blockchainDir);
|
||||
}
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
if (dumpBlockchainData) {
|
||||
txFileManager.shutDown();
|
||||
txOutputFileManager.shutDown();
|
||||
jsonFileManager.shutDown();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -23,9 +23,8 @@ import java.util.List;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
//TODO sync up with data model
|
||||
@Value
|
||||
public class JsonTx {
|
||||
class JsonTx {
|
||||
private final String txVersion = Version.BSQ_TX_VERSION;
|
||||
private final String id;
|
||||
private final int blockHeight;
|
||||
@ -36,4 +35,6 @@ public class JsonTx {
|
||||
private final JsonTxType txType;
|
||||
private final String txTypeDisplayString;
|
||||
private final long burntFee;
|
||||
// If not set it is -1. LockTime of 0 is a valid value.
|
||||
private final int unlockBlockHeight;
|
||||
}
|
||||
|
@ -21,14 +21,13 @@ import lombok.Value;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
//TODO sync up with data model
|
||||
@Value
|
||||
@Immutable
|
||||
public class JsonTxInput {
|
||||
private final int spendingTxOutputIndex;
|
||||
private final String spendingTxId;
|
||||
class JsonTxInput {
|
||||
private final int spendingTxOutputIndex; // connectedTxOutputIndex
|
||||
private final String spendingTxId; // connectedTxOutputTxId
|
||||
private final long bsqAmount;
|
||||
private final boolean isVerified;
|
||||
private final boolean isVerified; // isBsqTxOutputType
|
||||
private final String address;
|
||||
private final long time;
|
||||
}
|
||||
|
@ -21,7 +21,8 @@ import bisq.common.app.Version;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
//TODO sync up with data model
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Value
|
||||
public class JsonTxOutput {
|
||||
private final String txVersion = Version.BSQ_TX_VERSION;
|
||||
@ -30,15 +31,21 @@ public class JsonTxOutput {
|
||||
private final long bsqAmount;
|
||||
private final long btcAmount;
|
||||
private final int height;
|
||||
private final boolean isVerified;
|
||||
private final boolean isVerified; // isBsqTxOutputType
|
||||
private final long burntFee;
|
||||
private final String address;
|
||||
@Nullable
|
||||
private final JsonScriptPubKey scriptPubKey;
|
||||
@Nullable
|
||||
private final JsonSpentInfo spentInfo;
|
||||
private final long time;
|
||||
private final JsonTxType txType;
|
||||
private final String txTypeDisplayString;
|
||||
private final JsonTxOutputType txOutputType; // new
|
||||
private final String txOutputTypeDisplayString; // new
|
||||
@Nullable
|
||||
private final String opReturn;
|
||||
private final int lockTime; // new
|
||||
|
||||
public String getId() {
|
||||
return txId + ":" + outputIndex;
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 bisq.core.dao.node.json;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
// Need to be in sync with TxOutputType
|
||||
public enum JsonTxOutputType {
|
||||
UNDEFINED("Undefined"),
|
||||
GENESIS_OUTPUT("Genesis"),
|
||||
BSQ_OUTPUT("BSQ"),
|
||||
BTC_OUTPUT("BTC"),
|
||||
PROPOSAL_OP_RETURN_OUTPUT("Proposal opReturn"),
|
||||
COMP_REQ_OP_RETURN_OUTPUT("Compensation request opReturn"),
|
||||
CONFISCATE_BOND_OP_RETURN_OUTPUT("Confiscate bond opReturn"),
|
||||
ISSUANCE_CANDIDATE_OUTPUT("Issuance candidate"),
|
||||
BLIND_VOTE_LOCK_STAKE_OUTPUT("Blind vote lock stake"),
|
||||
BLIND_VOTE_OP_RETURN_OUTPUT("Blind vote opReturn"),
|
||||
VOTE_REVEAL_UNLOCK_STAKE_OUTPUT("Vote reveal unlock stake"),
|
||||
VOTE_REVEAL_OP_RETURN_OUTPUT("Vote reveal opReturn"),
|
||||
LOCKUP("Lockup"),
|
||||
LOCKUP_OP_RETURN_OUTPUT("Lockup opReturn"),
|
||||
UNLOCK("Unlock"),
|
||||
INVALID_OUTPUT("Invalid");
|
||||
|
||||
@Getter
|
||||
private String displayString;
|
||||
|
||||
JsonTxOutputType(String displayString) {
|
||||
this.displayString = displayString;
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ package bisq.core.dao.node.json;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
//TODO sync up with data model
|
||||
// Need to be in sync with TxOutputType
|
||||
public enum JsonTxType {
|
||||
UNDEFINED_TX_TYPE("Undefined"),
|
||||
UNVERIFIED("Unverified"),
|
||||
@ -27,13 +27,12 @@ public enum JsonTxType {
|
||||
GENESIS("Genesis"),
|
||||
TRANSFER_BSQ("Transfer BSQ"),
|
||||
PAY_TRADE_FEE("Pay trade fee"),
|
||||
PROPOSAL("Ballot"),
|
||||
PROPOSAL("Proposal"),
|
||||
COMPENSATION_REQUEST("Compensation request"),
|
||||
VOTE("Vote"),
|
||||
BLIND_VOTE("Blind vote"),
|
||||
VOTE_REVEAL("Vote reveal"),
|
||||
LOCK_UP("Lockup"),
|
||||
UN_LOCK("Unlock");
|
||||
LOCKUP("Lockup"),
|
||||
UNLOCK("Unlock");
|
||||
|
||||
@Getter
|
||||
private String displayString;
|
||||
|
@ -120,10 +120,6 @@ public class BsqStateService implements DaoSetupService {
|
||||
return bsqState.getClone();
|
||||
}
|
||||
|
||||
public LinkedList<Block> getBlocksFromState(BsqState bsqState) {
|
||||
return new LinkedList<>(bsqState.getBlocks());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ChainHeight
|
||||
|
@ -29,6 +29,8 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@ -101,7 +103,7 @@ public class SnapshotManager implements BsqStateListener {
|
||||
checkNotNull(storage, "storage must not be null");
|
||||
BsqState persisted = storage.initAndGetPersisted(bsqState, 100);
|
||||
if (persisted != null) {
|
||||
log.info("applySnapshot persisted.chainHeadHeight=" + bsqStateService.getBlocksFromState(persisted).getLast().getHeight());
|
||||
log.info("applySnapshot persisted.chainHeadHeight=" + new LinkedList<>(persisted.getBlocks()).getLast().getHeight());
|
||||
bsqStateService.applySnapshot(persisted);
|
||||
} else {
|
||||
log.info("Try to apply snapshot but no stored snapshot available");
|
||||
|
Loading…
Reference in New Issue
Block a user