Skip to content

Commit

Permalink
Merge pull request #2532 from ManfredKarrer/add-hash-of-dao-state
Browse files Browse the repository at this point in the history
Add hash of dao state
  • Loading branch information
ManfredKarrer authored Mar 16, 2019
2 parents ffaf0b3 + b7941c8 commit 545eb8c
Show file tree
Hide file tree
Showing 95 changed files with 5,378 additions and 141 deletions.
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
73 changes: 72 additions & 1 deletion common/src/main/proto/pb.proto
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ 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;
GetDaoStateHashesRequest get_dao_state_hashes_request = 35;
GetDaoStateHashesResponse get_dao_state_hashes_response = 36;
NewProposalStateHashMessage new_proposal_state_hash_message = 37;
GetProposalStateHashesRequest get_proposal_state_hashes_request = 38;
GetProposalStateHashesResponse get_proposal_state_hashes_response = 39;
NewBlindVoteStateHashMessage new_blind_vote_state_hash_message = 40;
GetBlindVoteStateHashesRequest get_blind_vote_state_hashes_request = 41;
GetBlindVoteStateHashesResponse get_blind_vote_state_hashes_response = 42;
}
}

Expand Down Expand Up @@ -324,6 +333,48 @@ message NewBlockBroadcastMessage {
message RepublishGovernanceDataRequest {
}

message NewDaoStateHashMessage {
DaoStateHash state_hash = 1;
}

message NewProposalStateHashMessage {
ProposalStateHash state_hash = 1;
}

message NewBlindVoteStateHashMessage {
BlindVoteStateHash state_hash = 1;
}

message GetDaoStateHashesRequest {
int32 height = 1;
int32 nonce = 2;
}

message GetProposalStateHashesRequest {
int32 height = 1;
int32 nonce = 2;
}

message GetBlindVoteStateHashesRequest {
int32 height = 1;
int32 nonce = 2;
}

message GetDaoStateHashesResponse {
repeated DaoStateHash state_hashes = 1;
int32 request_nonce = 2;
}

message GetProposalStateHashesResponse {
repeated ProposalStateHash state_hashes = 1;
int32 request_nonce = 2;
}

message GetBlindVoteStateHashesResponse {
repeated BlindVoteStateHash state_hashes = 1;
int32 request_nonce = 2;
}

///////////////////////////////////////////////////////////////////////////////////////////
// Payload
///////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -915,7 +966,6 @@ message AdvancedCashAccountPayload {
string account_nr = 1;
}


///////////////////////////////////////////////////////////////////////////////////////////
// PersistableEnvelope
///////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -1713,6 +1763,27 @@ message DecryptedBallotsWithMerits {

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

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

message ProposalStateHash {
int32 height = 1;
bytes hash = 2;
bytes prev_hash = 3;
int32 num_proposals = 4;
}

message BlindVoteStateHash {
int32 height = 1;
bytes hash = 2;
bytes prev_hash = 3;
int32 num_blind_votes = 4;
}

///////////////////////////////////////////////////////////////////////////////////////////
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
69 changes: 69 additions & 0 deletions core/src/main/java/bisq/core/dao/DaoEventCoordinator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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;

import bisq.core.dao.monitoring.DaoStateMonitoringService;
import bisq.core.dao.state.DaoStateListener;
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.DaoStateSnapshotService;
import bisq.core.dao.state.model.blockchain.Block;

import javax.inject.Inject;

public class DaoEventCoordinator implements DaoSetupService, DaoStateListener {
private final DaoStateService daoStateService;
private final DaoStateSnapshotService daoStateSnapshotService;
private final DaoStateMonitoringService daoStateMonitoringService;

@Inject
public DaoEventCoordinator(DaoStateService daoStateService,
DaoStateSnapshotService daoStateSnapshotService,
DaoStateMonitoringService daoStateMonitoringService) {
this.daoStateService = daoStateService;
this.daoStateSnapshotService = daoStateSnapshotService;
this.daoStateMonitoringService = daoStateMonitoringService;
}


///////////////////////////////////////////////////////////////////////////////////////////
// DaoSetupService
///////////////////////////////////////////////////////////////////////////////////////////

@Override
public void addListeners() {
this.daoStateService.addDaoStateListener(this);
}

@Override
public void start() {
}


///////////////////////////////////////////////////////////////////////////////////////////
// DaoStateListener
///////////////////////////////////////////////////////////////////////////////////////////

// We listen onDaoStateChanged to ensure the dao state has been processed from listener clients after parsing.
// We need to listen during batch processing as well to write snapshots during that process.
@Override
public void onDaoStateChanged(Block block) {
// We need to execute first the daoStateMonitoringService
daoStateMonitoringService.createHashFromBlock(block);
daoStateSnapshotService.maybeCreateSnapshot(block);
}
}
13 changes: 13 additions & 0 deletions core/src/main/java/bisq/core/dao/DaoModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@
import bisq.core.dao.governance.voteresult.VoteResultService;
import bisq.core.dao.governance.voteresult.issuance.IssuanceService;
import bisq.core.dao.governance.votereveal.VoteRevealService;
import bisq.core.dao.monitoring.BlindVoteStateMonitoringService;
import bisq.core.dao.monitoring.DaoStateMonitoringService;
import bisq.core.dao.monitoring.ProposalStateMonitoringService;
import bisq.core.dao.monitoring.network.BlindVoteStateNetworkService;
import bisq.core.dao.monitoring.network.DaoStateNetworkService;
import bisq.core.dao.monitoring.network.ProposalStateNetworkService;
import bisq.core.dao.node.BsqNodeProvider;
import bisq.core.dao.node.explorer.ExportJsonFilesService;
import bisq.core.dao.node.full.FullNode;
Expand Down Expand Up @@ -99,6 +105,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 +123,12 @@ 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(ProposalStateMonitoringService.class).in(Singleton.class);
bind(ProposalStateNetworkService.class).in(Singleton.class);
bind(BlindVoteStateMonitoringService.class).in(Singleton.class);
bind(BlindVoteStateNetworkService.class).in(Singleton.class);
bind(UnconfirmedBsqChangeOutputListService.class).in(Singleton.class);

bind(ExportJsonFilesService.class).in(Singleton.class);
Expand Down
18 changes: 17 additions & 1 deletion core/src/main/java/bisq/core/dao/DaoSetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
import bisq.core.dao.governance.voteresult.MissingDataRequestService;
import bisq.core.dao.governance.voteresult.VoteResultService;
import bisq.core.dao.governance.votereveal.VoteRevealService;
import bisq.core.dao.monitoring.BlindVoteStateMonitoringService;
import bisq.core.dao.monitoring.DaoStateMonitoringService;
import bisq.core.dao.monitoring.ProposalStateMonitoringService;
import bisq.core.dao.node.BsqNode;
import bisq.core.dao.node.BsqNodeProvider;
import bisq.core.dao.node.explorer.ExportJsonFilesService;
Expand Down Expand Up @@ -69,11 +72,20 @@ public DaoSetup(BsqNodeProvider bsqNodeProvider,
ProofOfBurnService proofOfBurnService,
DaoFacade daoFacade,
ExportJsonFilesService exportJsonFilesService,
DaoKillSwitch daoKillSwitch) {
DaoKillSwitch daoKillSwitch,
DaoStateMonitoringService daoStateMonitoringService,
ProposalStateMonitoringService proposalStateMonitoringService,
BlindVoteStateMonitoringService blindVoteStateMonitoringService,
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 +104,10 @@ public DaoSetup(BsqNodeProvider bsqNodeProvider,
daoSetupServices.add(daoFacade);
daoSetupServices.add(exportJsonFilesService);
daoSetupServices.add(daoKillSwitch);
daoSetupServices.add(daoStateMonitoringService);
daoSetupServices.add(proposalStateMonitoringService);
daoSetupServices.add(blindVoteStateMonitoringService);

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 @@ -120,16 +120,23 @@ public List<BlindVote> getBlindVotesInPhaseAndCycle() {
.collect(Collectors.toList());
}

public List<BlindVote> getConfirmedBlindVotes() {
return blindVotePayloads.stream()
.filter(blindVotePayload -> blindVoteValidator.areDataFieldsValidAndTxConfirmed(blindVotePayload.getBlindVote()))
.map(BlindVotePayload::getBlindVote)
.collect(Collectors.toList());
}


///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////

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 +147,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 @@ -47,7 +47,7 @@ public class MyBlindVoteList extends PersistableList<BlindVote> implements Conse
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////

private MyBlindVoteList(List<BlindVote> list) {
public MyBlindVoteList(List<BlindVote> list) {
super(list);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ public MyBlindVoteListService(P2PService p2PService,
@Override
public void addListeners() {
daoStateService.addDaoStateListener(this);
p2PService.getNumConnectedPeers().addListener(numConnectedPeersListener);
}

@Override
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
Loading

0 comments on commit 545eb8c

Please sign in to comment.