Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hash of dao state #2532

Merged
merged 33 commits into from
Mar 16, 2019
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0d0713b
Remove optional setting of pubKeyScript
ManfredKarrer Mar 8, 2019
22c0388
Add comment
ManfredKarrer Mar 8, 2019
2a4270d
Merge branch 'master' into add-hash-of-dao-state
ManfredKarrer Mar 8, 2019
40b6505
Add monitoring for hash of DaoState
ManfredKarrer Mar 9, 2019
51ec876
Add removeLinebreaks parameter to toTruncatedString
ManfredKarrer Mar 9, 2019
fcd7997
Create chain of dao state hashes for monitoring consensus issues
ManfredKarrer Mar 11, 2019
d09e770
Add parseBlockchainComplete check
ManfredKarrer Mar 11, 2019
e7bfba0
Add comment
ManfredKarrer Mar 11, 2019
bbec682
Add UI for Dao state monitor
ManfredKarrer Mar 11, 2019
f560413
Update UI, remove checkArgument call
ManfredKarrer Mar 12, 2019
dbb0ba3
Add check for address
ManfredKarrer Mar 12, 2019
c280f30
Use domain data or sorting
ManfredKarrer Mar 13, 2019
47024d1
Show dash instead of N/A for prev hash at genesis height
ManfredKarrer Mar 13, 2019
d235e9c
Avoid logging at startup
ManfredKarrer Mar 13, 2019
eb3d65d
Add snapshot support for hashChain
ManfredKarrer Mar 14, 2019
9c01560
Call listeners only after batch of hashes is processed
ManfredKarrer Mar 14, 2019
2009c30
Refactor dao state monitor
ManfredKarrer Mar 15, 2019
3685270
Move monitor view to new tab
ManfredKarrer Mar 15, 2019
59bed76
Add proposal monitor view
ManfredKarrer Mar 15, 2019
3411cde
Reflect code review comments
ManfredKarrer Mar 15, 2019
52e1455
Refactor updateHashChain
ManfredKarrer Mar 15, 2019
2109c66
Add num proposals
ManfredKarrer Mar 15, 2019
4af7495
Add blind vote monitoring
ManfredKarrer Mar 16, 2019
933fa46
Fix table layout issue
ManfredKarrer Mar 16, 2019
ccbb578
Add peer to log
ManfredKarrer Mar 16, 2019
00e350e
Small fixes
ManfredKarrer Mar 16, 2019
e3dace8
Fix tests
ManfredKarrer Mar 16, 2019
e933584
Remove db store file
ManfredKarrer Mar 16, 2019
0b15246
Add updated db files
ManfredKarrer Mar 16, 2019
b222fd2
Change file name for DaoStateStore db file to DaoStateStore2, Cleanup
ManfredKarrer Mar 16, 2019
82e2a48
Add comments
ManfredKarrer Mar 16, 2019
0ba2f6f
Cleanup after code inspection
ManfredKarrer Mar 16, 2019
b7941c8
Merge branch 'master' into add-hash-of-dao-state
ManfredKarrer Mar 16, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion common/src/main/java/bisq/common/app/Capability.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ public enum Capability {
PROPOSAL,
BLIND_VOTE,
ACK_MSG,
BSQ_BLOCK
BSQ_BLOCK,
DAO_STATE
}
28 changes: 21 additions & 7 deletions common/src/main/java/bisq/common/util/Utilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public static ScheduledThreadPoolExecutor getScheduledThreadPoolExecutor(String
public static boolean isMacMenuBarDarkMode() {
try {
// check for exit status only. Once there are more modes than "dark" and "default", we might need to analyze string contents..
final Process process = Runtime.getRuntime().exec(new String[] {"defaults", "read", "-g", "AppleInterfaceStyle"});
Process process = Runtime.getRuntime().exec(new String[]{"defaults", "read", "-g", "AppleInterfaceStyle"});
process.waitFor(100, TimeUnit.MILLISECONDS);
return process.exitValue() == 0;
} catch (IOException | InterruptedException | IllegalThreadStateException ex) {
Expand Down Expand Up @@ -512,15 +512,29 @@ public static void checkCryptoPolicySetup() throws NoSuchAlgorithmException, Lim
throw new LimitedKeyStrengthException();
}

public static String toTruncatedString(Object message) {
return toTruncatedString(message, 200, true);
}

public static String toTruncatedString(Object message, int maxLength) {
if (message != null) {
return StringUtils.abbreviate(message.toString(), maxLength).replace("\n", "");
}
return "null";
return toTruncatedString(message, maxLength, true);
}

public static String toTruncatedString(Object message) {
return toTruncatedString(message, 200);
public static String toTruncatedString(Object message, boolean removeLinebreaks) {
return toTruncatedString(message, 200, removeLinebreaks);
}

public static String toTruncatedString(Object message, int maxLength, boolean removeLinebreaks) {
if (message == null)
return "null";


String result = StringUtils.abbreviate(message.toString(), maxLength);
if (removeLinebreaks)
return result.replace("\n", "");

return result;

}

public static String getRandomPrefix(int minLength, int maxLength) {
Expand Down
24 changes: 24 additions & 0 deletions common/src/main/proto/pb.proto
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ message NetworkEnvelope {
AddPersistableNetworkPayloadMessage add_persistable_network_payload_message = 31;
AckMessage ack_message = 32;
RepublishGovernanceDataRequest republish_governance_data_request = 33;
NewDaoStateHashMessage new_dao_state_hash_message = 34;
GetDaoStateHashRequest get_dao_state_hash_request = 35;
GetDaoStateHashResponse get_dao_state_hash_response = 36;
}
}

Expand Down Expand Up @@ -324,6 +327,16 @@ message NewBlockBroadcastMessage {
message RepublishGovernanceDataRequest {
}

message GetDaoStateHashRequest {
int32 from_block_height = 1;
int32 nonce = 2;
}

message GetDaoStateHashResponse {
repeated DaoStateHash dao_state_hashes = 1;
int32 request_nonce = 2;
}

///////////////////////////////////////////////////////////////////////////////////////////
// Payload
///////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -1713,6 +1726,17 @@ message DecryptedBallotsWithMerits {

message DaoStateStore {
BsqState bsq_state = 1;
repeated DaoStateHash dao_state_hash = 2;
}

message DaoStateHash {
int32 blockHeight = 1;
bytes hash = 2;
bytes prev_hash = 3;
}

message NewDaoStateHashMessage {
DaoStateHash dao_state_hash = 1;
}

///////////////////////////////////////////////////////////////////////////////////////////
Expand Down
9 changes: 6 additions & 3 deletions core/src/main/java/bisq/core/btc/BitcoinModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@ public BitcoinModule(Environment environment) {
protected void configure() {
// We we have selected BTC_DAO_TESTNET we use our master regtest node, otherwise the specified host or default
// (localhost)
String regTestHost = BisqEnvironment.getBaseCurrencyNetwork().isDaoTestNet() ?
"104.248.31.39" :
environment.getProperty(BtcOptionKeys.REG_TEST_HOST, String.class, RegTestHost.DEFAULT_HOST);
String regTestHost = environment.getProperty(BtcOptionKeys.REG_TEST_HOST, String.class, "");
if (regTestHost.isEmpty()) {
regTestHost = BisqEnvironment.getBaseCurrencyNetwork().isDaoTestNet() ?
"104.248.31.39" :
RegTestHost.DEFAULT_HOST;
}

RegTestHost.HOST = regTestHost;
if (Arrays.asList("localhost", "127.0.0.1").contains(regTestHost)) {
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/bisq/core/dao/DaoModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,14 @@
import bisq.core.dao.node.lite.network.LiteNodeNetworkService;
import bisq.core.dao.node.parser.BlockParser;
import bisq.core.dao.node.parser.TxParser;
import bisq.core.dao.state.DaoEventCoordinator;
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.DaoStateSnapshotService;
import bisq.core.dao.state.DaoStateStorageService;
import bisq.core.dao.state.GenesisTxInfo;
import bisq.core.dao.state.model.DaoState;
import bisq.core.dao.state.monitoring.DaoStateMonitoringService;
import bisq.core.dao.state.monitoring.network.DaoStateNetworkService;
import bisq.core.dao.state.unconfirmed.UnconfirmedBsqChangeOutputListService;

import bisq.common.app.AppModule;
Expand All @@ -99,6 +102,7 @@ public DaoModule(Environment environment) {
protected void configure() {
bind(DaoSetup.class).in(Singleton.class);
bind(DaoFacade.class).in(Singleton.class);
bind(DaoEventCoordinator.class).in(Singleton.class);
bind(DaoKillSwitch.class).in(Singleton.class);

// Node, parser
Expand All @@ -116,6 +120,8 @@ protected void configure() {
bind(DaoStateService.class).in(Singleton.class);
bind(DaoStateSnapshotService.class).in(Singleton.class);
bind(DaoStateStorageService.class).in(Singleton.class);
bind(DaoStateMonitoringService.class).in(Singleton.class);
bind(DaoStateNetworkService.class).in(Singleton.class);
bind(UnconfirmedBsqChangeOutputListService.class).in(Singleton.class);

bind(ExportJsonFilesService.class).in(Singleton.class);
Expand Down
13 changes: 12 additions & 1 deletion core/src/main/java/bisq/core/dao/DaoSetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
import bisq.core.dao.node.BsqNode;
import bisq.core.dao.node.BsqNodeProvider;
import bisq.core.dao.node.explorer.ExportJsonFilesService;
import bisq.core.dao.state.DaoEventCoordinator;
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.monitoring.DaoStateMonitoringService;

import com.google.inject.Inject;

Expand Down Expand Up @@ -69,11 +71,18 @@ public DaoSetup(BsqNodeProvider bsqNodeProvider,
ProofOfBurnService proofOfBurnService,
DaoFacade daoFacade,
ExportJsonFilesService exportJsonFilesService,
DaoKillSwitch daoKillSwitch) {
DaoKillSwitch daoKillSwitch,
DaoStateMonitoringService daoStateMonitoringService,
DaoEventCoordinator daoEventCoordinator) {

bsqNode = bsqNodeProvider.getBsqNode();

// We need to take care of order of execution.

// For order critical event flow we use the daoEventCoordinator to delegate the calls from anonymous listeners
// to concrete clients.
daoSetupServices.add(daoEventCoordinator);

daoSetupServices.add(daoStateService);
daoSetupServices.add(cycleService);
daoSetupServices.add(ballotListService);
Expand All @@ -92,6 +101,8 @@ public DaoSetup(BsqNodeProvider bsqNodeProvider,
daoSetupServices.add(daoFacade);
daoSetupServices.add(exportJsonFilesService);
daoSetupServices.add(daoKillSwitch);
daoSetupServices.add(daoStateMonitoringService);

daoSetupServices.add(bsqNodeProvider.getBsqNode());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public void onParseBlockChainComplete() {

@Override
public void onAdded(PersistableNetworkPayload payload) {
onAppendOnlyDataAdded(payload);
onAppendOnlyDataAdded(payload, true);
}


Expand All @@ -126,10 +126,10 @@ public List<BlindVote> getBlindVotesInPhaseAndCycle() {
///////////////////////////////////////////////////////////////////////////////////////////

private void fillListFromAppendOnlyDataStore() {
p2PService.getP2PDataStorage().getAppendOnlyDataStoreMap().values().forEach(this::onAppendOnlyDataAdded);
p2PService.getP2PDataStorage().getAppendOnlyDataStoreMap().values().forEach(e -> onAppendOnlyDataAdded(e, false));
}

private void onAppendOnlyDataAdded(PersistableNetworkPayload persistableNetworkPayload) {
private void onAppendOnlyDataAdded(PersistableNetworkPayload persistableNetworkPayload, boolean doLog) {
if (persistableNetworkPayload instanceof BlindVotePayload) {
BlindVotePayload blindVotePayload = (BlindVotePayload) persistableNetworkPayload;
if (!blindVotePayloads.contains(blindVotePayload)) {
Expand All @@ -140,7 +140,9 @@ private void onAppendOnlyDataAdded(PersistableNetworkPayload persistableNetworkP
if (blindVoteValidator.areDataFieldsValid(blindVote)) {
// We don't validate as we might receive blindVotes from other cycles or phases at startup.
blindVotePayloads.add(blindVotePayload);
log.info("We received a blindVotePayload. blindVoteTxId={}", txId);
if (doLog) {
log.info("We received a blindVotePayload. blindVoteTxId={}", txId);
}
} else {
log.warn("We received an invalid blindVotePayload. blindVoteTxId={}", txId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public void start() {
public void onNewBlockHeight(int blockHeight) {
if (blockHeight != genesisBlockHeight)
maybeCreateNewCycle(blockHeight, daoStateService.getCycles())
.ifPresent(daoStateService.getCycles()::add);
.ifPresent(daoStateService::addCycle);
}


Expand All @@ -88,7 +88,7 @@ public void onNewBlockHeight(int blockHeight) {
///////////////////////////////////////////////////////////////////////////////////////////

public void addFirstCycle() {
daoStateService.getCycles().add(getFirstCycle());
daoStateService.addCycle(getFirstCycle());
}

public int getCycleIndex(Cycle cycle) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public void start() {

@Override
public void onAdded(ProtectedStorageEntry entry) {
onProtectedDataAdded(entry);
onProtectedDataAdded(entry, true);
}

@Override
Expand All @@ -146,7 +146,7 @@ public void onRemoved(ProtectedStorageEntry entry) {

@Override
public void onAdded(PersistableNetworkPayload payload) {
onAppendOnlyDataAdded(payload);
onAppendOnlyDataAdded(payload, true);
}


Expand Down Expand Up @@ -190,11 +190,11 @@ public List<Proposal> getValidatedProposals() {
///////////////////////////////////////////////////////////////////////////////////////////

private void fillListFromProtectedStore() {
p2PService.getDataMap().values().forEach(this::onProtectedDataAdded);
p2PService.getDataMap().values().forEach(e -> onProtectedDataAdded(e, false));
}

private void fillListFromAppendOnlyDataStore() {
p2PService.getP2PDataStorage().getAppendOnlyDataStoreMap().values().forEach(this::onAppendOnlyDataAdded);
p2PService.getP2PDataStorage().getAppendOnlyDataStoreMap().values().forEach(e -> onAppendOnlyDataAdded(e, false));
}

private void publishToAppendOnlyDataStore() {
Expand All @@ -211,16 +211,18 @@ private void publishToAppendOnlyDataStore() {
});
}

private void onProtectedDataAdded(ProtectedStorageEntry entry) {
private void onProtectedDataAdded(ProtectedStorageEntry entry, boolean doLog) {
ProtectedStoragePayload protectedStoragePayload = entry.getProtectedStoragePayload();
if (protectedStoragePayload instanceof TempProposalPayload) {
Proposal proposal = ((TempProposalPayload) protectedStoragePayload).getProposal();
// We do not validate if we are in current cycle and if tx is confirmed yet as the tx might be not
// available/confirmed. But we check if we are in the proposal phase.
if (!tempProposals.contains(proposal)) {
if (proposalValidator.isValidOrUnconfirmed(proposal)) {
log.info("We received a TempProposalPayload and store it to our protectedStoreList. proposalTxId={}",
proposal.getTxId());
if (doLog) {
log.info("We received a TempProposalPayload and store it to our protectedStoreList. proposalTxId={}",
proposal.getTxId());
}
tempProposals.add(proposal);
} else {
log.debug("We received an invalid proposal from the P2P network. Proposal.txId={}, blockHeight={}",
Expand Down Expand Up @@ -256,14 +258,16 @@ private void onProtectedDataRemoved(ProtectedStorageEntry entry) {
}
}

private void onAppendOnlyDataAdded(PersistableNetworkPayload persistableNetworkPayload) {
private void onAppendOnlyDataAdded(PersistableNetworkPayload persistableNetworkPayload, boolean doLog) {
if (persistableNetworkPayload instanceof ProposalPayload) {
ProposalPayload proposalPayload = (ProposalPayload) persistableNetworkPayload;
if (!proposalPayloads.contains(proposalPayload)) {
Proposal proposal = proposalPayload.getProposal();
if (proposalValidator.areDataFieldsValid(proposal)) {
log.info("We received a ProposalPayload and store it to our appendOnlyStoreList. proposalTxId={}",
proposal.getTxId());
if (doLog) {
log.info("We received a ProposalPayload and store it to our appendOnlyStoreList. proposalTxId={}",
proposal.getTxId());
}
proposalPayloads.add(proposalPayload);
} else {
log.warn("We received a invalid append-only proposal from the P2P network. " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ private void maybeCalculateVoteResult(int chainHeight) {
}

// Those which did not get accepted will be added to the nonBsq map
// FIXME add check for cycle as now we call addNonBsqTxOutput for past rejected comp requests as well
daoStateService.getIssuanceCandidateTxOutputs().stream()
.filter(txOutput -> !daoStateService.isIssuanceTx(txOutput.getTxId()))
.forEach(daoStateService::addNonBsqTxOutput);
Expand Down Expand Up @@ -304,6 +305,8 @@ private Function<TxOutput, DecryptedBallotsWithMerits> txOutputToDecryptedBallot
return getDecryptedBallotsWithMerits(voteRevealTxId, currentCycle, voteRevealOpReturnData,
blindVoteTxId, hashOfBlindVoteList, blindVoteStake, optionalBlindVote.get());
}

// We are missing P2P network data
return getEmptyDecryptedBallotsWithMerits(voteRevealTxId, blindVoteTxId, hashOfBlindVoteList,
blindVoteStake);
} catch (Throwable e) {
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/java/bisq/core/dao/node/full/FullNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ private void parseBlocksIfNewBlockAvailable(int chainHeight) {
} else {
log.info("parseBlocksIfNewBlockAvailable did not result in a new block, so we complete.");
log.info("parse {} blocks took {} seconds", blocksToParseInBatch, (System.currentTimeMillis() - parseInBatchStartTime) / 1000d);
onParseBlockChainComplete();
if (!parseBlockchainComplete) {
onParseBlockChainComplete();
}
}
},
this::handleError);
Expand Down
8 changes: 2 additions & 6 deletions core/src/main/java/bisq/core/dao/node/full/RpcService.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ public class RpcService {
private final String rpcPassword;
private final String rpcPort;
private final String rpcBlockPort;
private final boolean dumpBlockchainData;

private BtcdClient client;
private BtcdDaemon daemon;
Expand All @@ -92,8 +91,7 @@ public class RpcService {
@Inject
public RpcService(Preferences preferences,
@Named(DaoOptionKeys.RPC_PORT) String rpcPort,
@Named(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT) String rpcBlockPort,
@Named(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA) boolean dumpBlockchainData) {
@Named(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT) String rpcBlockPort) {
this.rpcUser = preferences.getRpcUser();
this.rpcPassword = preferences.getRpcPw();

Expand All @@ -109,8 +107,6 @@ public RpcService(Preferences preferences,
"18443"; // regtest
this.rpcBlockPort = rpcBlockPort != null && !rpcBlockPort.isEmpty() ? rpcBlockPort : "5125";

this.dumpBlockchainData = dumpBlockchainData;

log.info("Version of btcd-cli4j library: {}", BtcdCli4jVersion.VERSION);
}

Expand Down Expand Up @@ -305,7 +301,7 @@ private RawTx getTxFromRawTransaction(RawTransaction rawBtcTx, com.neemre.btcdcl
// 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;
PubKeyScript pubKeyScript = dumpBlockchainData ? new PubKeyScript(scriptPubKey) : null;
PubKeyScript pubKeyScript = new PubKeyScript(scriptPubKey);
return new RawTxOutput(rawBtcTxOutput.getN(),
rawBtcTxOutput.getValue().movePointRight(8).longValue(),
rawBtcTx.getTxId(),
Expand Down
Loading