mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 15:10:44 +01:00
Use BlockHash and data for append-only store
We add the blockHash of the 10th block in the break before the relevant phase as part of the hash in the appen-only data. Together with the date tolerance we get control over the time when the data has been added. This protects agains various attacks (data withhold and publish late attack). - Implement DateTolerantPayload at BlindVoteAppendOnlyPayload and ProposalAppendOnlyPayload - Implement ExpirablePayload at ProposalPayload and BlindVotePayload - Add blockHash and data at BlindVoteAppendOnlyPayload and ProposalAppendOnlyPayload - Add ClosedBallotsView
This commit is contained in:
parent
f59aca99ee
commit
90e310263b
7 changed files with 326 additions and 17 deletions
|
@ -28,6 +28,7 @@ import bisq.desktop.components.MenuItem;
|
|||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.dao.DaoView;
|
||||
import bisq.desktop.main.dao.voting.active.ActiveBallotsView;
|
||||
import bisq.desktop.main.dao.voting.closed.ClosedBallotsView;
|
||||
import bisq.desktop.main.dao.voting.dashboard.VotingDashboardView;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
|
@ -51,7 +52,7 @@ public class VotingView extends ActivatableViewAndModel {
|
|||
private final ViewLoader viewLoader;
|
||||
private final Navigation navigation;
|
||||
|
||||
private MenuItem dashboard, ballots;
|
||||
private MenuItem dashboard, activeBallots, closedBallots;
|
||||
private Navigation.Listener listener;
|
||||
|
||||
@FXML
|
||||
|
@ -81,15 +82,18 @@ public class VotingView extends ActivatableViewAndModel {
|
|||
final List<Class<? extends View>> baseNavPath = Arrays.asList(MainView.class, DaoView.class, VotingView.class);
|
||||
dashboard = new MenuItem(navigation, toggleGroup, Res.get("shared.dashboard"),
|
||||
VotingDashboardView.class, AwesomeIcon.DASHBOARD, baseNavPath);
|
||||
ballots = new MenuItem(navigation, toggleGroup, Res.get("dao.voting.menuItem.ballots"),
|
||||
activeBallots = new MenuItem(navigation, toggleGroup, Res.get("dao.voting.menuItem.activeBallots"),
|
||||
ActiveBallotsView.class, AwesomeIcon.LIST_UL, baseNavPath);
|
||||
leftVBox.getChildren().addAll(dashboard, ballots);
|
||||
closedBallots = new MenuItem(navigation, toggleGroup, Res.get("dao.voting.menuItem.closedBallots"),
|
||||
ClosedBallotsView.class, AwesomeIcon.LIST_UL, baseNavPath);
|
||||
leftVBox.getChildren().addAll(dashboard, activeBallots, closedBallots);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
dashboard.activate();
|
||||
ballots.activate();
|
||||
activeBallots.activate();
|
||||
closedBallots.activate();
|
||||
|
||||
navigation.addListener(listener);
|
||||
ViewPath viewPath = navigation.getCurrentPath();
|
||||
|
@ -111,7 +115,8 @@ public class VotingView extends ActivatableViewAndModel {
|
|||
navigation.removeListener(listener);
|
||||
|
||||
dashboard.deactivate();
|
||||
ballots.deactivate();
|
||||
activeBallots.deactivate();
|
||||
closedBallots.deactivate();
|
||||
}
|
||||
|
||||
private void loadView(Class<? extends View> viewClass) {
|
||||
|
@ -119,7 +124,8 @@ public class VotingView extends ActivatableViewAndModel {
|
|||
content.getChildren().setAll(view.getRoot());
|
||||
|
||||
if (view instanceof VotingDashboardView) dashboard.setSelected(true);
|
||||
else if (view instanceof ActiveBallotsView) ballots.setSelected(true);
|
||||
else if (view instanceof ActiveBallotsView) activeBallots.setSelected(true);
|
||||
else if (view instanceof ClosedBallotsView) closedBallots.setSelected(true);
|
||||
}
|
||||
|
||||
public Class<? extends View> getSelectedViewClass() {
|
||||
|
|
|
@ -33,6 +33,8 @@ import bisq.core.btc.exceptions.WalletException;
|
|||
import bisq.core.btc.wallet.BsqBalanceListener;
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.state.BlockListener;
|
||||
import bisq.core.dao.state.blockchain.Block;
|
||||
import bisq.core.dao.state.period.DaoPhase;
|
||||
import bisq.core.dao.voting.ballot.Ballot;
|
||||
import bisq.core.dao.voting.ballot.vote.BooleanVote;
|
||||
|
@ -71,7 +73,7 @@ import static bisq.desktop.util.FormBuilder.addLabelInputTextField;
|
|||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
|
||||
@FxmlView
|
||||
public class ActiveBallotsView extends BaseProposalView implements BsqBalanceListener {
|
||||
public class ActiveBallotsView extends BaseProposalView implements BsqBalanceListener, BlockListener {
|
||||
private Button acceptButton, rejectButton, removeMyVoteButton, voteButton;
|
||||
private InputTextField stakeInputTextField;
|
||||
private BusyAnimation voteButtonBusyAnimation;
|
||||
|
@ -115,6 +117,10 @@ public class ActiveBallotsView extends BaseProposalView implements BsqBalanceLis
|
|||
bsqWalletService.getLockedInBondsBalance());
|
||||
|
||||
voteButton.setOnAction(e -> onVote());
|
||||
|
||||
daoFacade.addBlockListener(this);
|
||||
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
|
||||
|
@ -140,6 +146,15 @@ public class ActiveBallotsView extends BaseProposalView implements BsqBalanceLis
|
|||
bsqFormatter.formatCoinWithCode(confirmedBalance)));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BlockListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(Block block) {
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
|
@ -151,6 +166,7 @@ public class ActiveBallotsView extends BaseProposalView implements BsqBalanceLis
|
|||
proposalBaseProposalListItems.setAll(list.stream()
|
||||
.map(ballot -> new ActiveBallotListItem(ballot, daoFacade, bsqWalletService, bsqFormatter))
|
||||
.collect(Collectors.toSet()));
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -276,15 +292,13 @@ public class ActiveBallotsView extends BaseProposalView implements BsqBalanceLis
|
|||
}
|
||||
|
||||
private void updateButtons() {
|
||||
if (selectedBaseProposalListItem != null && proposalDisplay != null) {
|
||||
final boolean isBlindVotePhase = daoFacade.phaseProperty().get() == DaoPhase.Phase.BLIND_VOTE;
|
||||
stakeInputTextField.setDisable(!isBlindVotePhase);
|
||||
voteButton.setDisable(!isBlindVotePhase);
|
||||
|
||||
acceptButton.setDisable(!isBlindVotePhase);
|
||||
rejectButton.setDisable(!isBlindVotePhase);
|
||||
removeMyVoteButton.setDisable(!isBlindVotePhase);
|
||||
}
|
||||
if (acceptButton != null) acceptButton.setDisable(!isBlindVotePhase);
|
||||
if (rejectButton != null) rejectButton.setDisable(!isBlindVotePhase);
|
||||
if (removeMyVoteButton != null) removeMyVoteButton.setDisable(!isBlindVotePhase);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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.desktop.main.dao.voting.closed;
|
||||
|
||||
import bisq.desktop.main.dao.BaseProposalListItem;
|
||||
import bisq.desktop.util.BsqFormatter;
|
||||
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.state.period.DaoPhase;
|
||||
import bisq.core.dao.voting.ballot.Ballot;
|
||||
import bisq.core.dao.voting.ballot.vote.BooleanVote;
|
||||
import bisq.core.dao.voting.ballot.vote.Vote;
|
||||
import bisq.core.dao.voting.proposal.Proposal;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@ToString
|
||||
@Slf4j
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ClosedBallotListItem extends BaseProposalListItem {
|
||||
@Getter
|
||||
private final Ballot ballot;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public ClosedBallotListItem(Ballot ballot,
|
||||
DaoFacade daoFacade,
|
||||
BsqWalletService bsqWalletService,
|
||||
BsqFormatter bsqFormatter) {
|
||||
super(daoFacade,
|
||||
bsqWalletService,
|
||||
bsqFormatter);
|
||||
|
||||
this.ballot = ballot;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPhaseChanged(DaoPhase.Phase phase) {
|
||||
super.onPhaseChanged(phase);
|
||||
|
||||
final Vote vote = ballot.getVote();
|
||||
if (vote != null) {
|
||||
imageView.setVisible(true);
|
||||
if (vote instanceof BooleanVote) {
|
||||
if (((BooleanVote) vote).isAccepted()) {
|
||||
imageView.setId("accepted");
|
||||
} else {
|
||||
imageView.setId("rejected");
|
||||
}
|
||||
} else {
|
||||
//TODO
|
||||
}
|
||||
} else {
|
||||
imageView.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Proposal getProposal() {
|
||||
return ballot.getProposal();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.voting.closed.ClosedBallotsView"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0" AnchorPane.topAnchor="0.0"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
||||
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" halignment="RIGHT" minWidth="160.0"/>
|
||||
<ColumnConstraints hgrow="ALWAYS" minWidth="300.0"/>
|
||||
</columnConstraints>
|
||||
</GridPane>
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* 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.desktop.main.dao.voting.closed;
|
||||
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.main.dao.BaseProposalListItem;
|
||||
import bisq.desktop.main.dao.BaseProposalView;
|
||||
import bisq.desktop.util.BSFormatter;
|
||||
import bisq.desktop.util.BsqFormatter;
|
||||
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.voting.ballot.Ballot;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.image.ImageView;
|
||||
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
|
||||
import javafx.collections.ListChangeListener;
|
||||
|
||||
import javafx.util.Callback;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@FxmlView
|
||||
public class ClosedBallotsView extends BaseProposalView {
|
||||
private ListChangeListener<Ballot> listChangeListener;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private ClosedBallotsView(DaoFacade daoFacade,
|
||||
BsqWalletService bsqWalletService,
|
||||
BsqFormatter bsqFormatter,
|
||||
BSFormatter btcFormatter) {
|
||||
|
||||
super(daoFacade, bsqWalletService, bsqFormatter, btcFormatter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
|
||||
createProposalsTableView();
|
||||
createEmptyProposalDisplay();
|
||||
|
||||
listChangeListener = c -> updateListItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
super.activate();
|
||||
|
||||
daoFacade.getClosedBallots().addListener(listChangeListener);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
super.deactivate();
|
||||
|
||||
daoFacade.getClosedBallots().removeListener(listChangeListener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void fillListItems() {
|
||||
List<Ballot> list = daoFacade.getClosedBallots();
|
||||
proposalBaseProposalListItems.setAll(list.stream()
|
||||
.map(ballot -> new ClosedBallotListItem(ballot, daoFacade, bsqWalletService, bsqFormatter))
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
private ClosedBallotListItem getBallotListItem() {
|
||||
return (ClosedBallotListItem) selectedBaseProposalListItem;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TableColumns
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void createProposalColumns(TableView<BaseProposalListItem> tableView) {
|
||||
super.createProposalColumns(tableView);
|
||||
createConfidenceColumn(tableView);
|
||||
|
||||
TableColumn<BaseProposalListItem, BaseProposalListItem> actionColumn = new TableColumn<>();
|
||||
actionColumn.setMinWidth(130);
|
||||
actionColumn.setMaxWidth(actionColumn.getMinWidth());
|
||||
|
||||
actionColumn.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
|
||||
actionColumn.setCellFactory(new Callback<TableColumn<BaseProposalListItem, BaseProposalListItem>,
|
||||
TableCell<BaseProposalListItem, BaseProposalListItem>>() {
|
||||
|
||||
@Override
|
||||
public TableCell<BaseProposalListItem, BaseProposalListItem> call(TableColumn<BaseProposalListItem,
|
||||
BaseProposalListItem> column) {
|
||||
return new TableCell<BaseProposalListItem, BaseProposalListItem>() {
|
||||
ImageView imageView;
|
||||
|
||||
@Override
|
||||
public void updateItem(final BaseProposalListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
ClosedBallotListItem closedBallotListItem = (ClosedBallotListItem) item;
|
||||
if (imageView == null) {
|
||||
imageView = closedBallotListItem.getImageView();
|
||||
setGraphic(imageView);
|
||||
}
|
||||
closedBallotListItem.onPhaseChanged(currentPhase);
|
||||
} else {
|
||||
setGraphic(null);
|
||||
if (imageView != null)
|
||||
imageView = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
actionColumn.setComparator(Comparator.comparing(BaseProposalListItem::getConfirmations));
|
||||
tableView.getColumns().add(actionColumn);
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.voting.history.VotingHistoryView"
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.voting.closed.VotingHistoryView"
|
||||
hgap="5.0" vgap="5.0"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="-10.0"
|
|
@ -15,7 +15,7 @@
|
|||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.dao.voting.history;
|
||||
package bisq.desktop.main.dao.voting.closed;
|
||||
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
Loading…
Add table
Reference in a new issue