Skip to content

Commit

Permalink
Merge pull request bisq-network#1813 from ManfredKarrer/add-reimburse…
Browse files Browse the repository at this point in the history
…ment-proposal

Add support for reimbursement requests
  • Loading branch information
ManfredKarrer authored Oct 24, 2018
2 parents 1ee8578 + 7be08fe commit 5113ccc
Show file tree
Hide file tree
Showing 54 changed files with 785 additions and 158 deletions.
1 change: 1 addition & 0 deletions common/src/main/java/bisq/common/app/Version.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public static void printVersion() {

//TODO move to consensus area
public static final byte COMPENSATION_REQUEST = (byte) 0x01;
public static final byte REIMBURSEMENT_REQUEST = (byte) 0x01;
public static final byte PROPOSAL = (byte) 0x01;
public static final byte BLIND_VOTE = (byte) 0x01;
public static final byte VOTE_REVEAL = (byte) 0x01;
Expand Down
47 changes: 28 additions & 19 deletions common/src/main/proto/pb.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1360,10 +1360,11 @@ enum TxType {
PAY_TRADE_FEE = 6;
PROPOSAL = 7;
COMPENSATION_REQUEST = 8;
BLIND_VOTE = 9;
VOTE_REVEAL = 10;
LOCKUP = 11;
UNLOCK = 12;
REIMBURSEMENT_REQUEST = 9;
BLIND_VOTE = 10;
VOTE_REVEAL = 11;
LOCKUP = 12;
UNLOCK = 13;
}

message TxInput {
Expand Down Expand Up @@ -1403,16 +1404,17 @@ enum TxOutputType {
BTC_OUTPUT = 4;
PROPOSAL_OP_RETURN_OUTPUT = 5;
COMP_REQ_OP_RETURN_OUTPUT = 6;
CONFISCATE_BOND_OP_RETURN_OUTPUT = 7;
ISSUANCE_CANDIDATE_OUTPUT = 8;
BLIND_VOTE_LOCK_STAKE_OUTPUT = 9;
BLIND_VOTE_OP_RETURN_OUTPUT = 10;
VOTE_REVEAL_UNLOCK_STAKE_OUTPUT = 11;
VOTE_REVEAL_OP_RETURN_OUTPUT = 12;
LOCKUP_OUTPUT = 13;
LOCKUP_OP_RETURN_OUTPUT = 14;
UNLOCK_OUTPUT = 15;
INVALID_OUTPUT = 16;
REIMBURSEMENT_OP_RETURN_OUTPUT = 7;
CONFISCATE_BOND_OP_RETURN_OUTPUT = 8;
ISSUANCE_CANDIDATE_OUTPUT = 9;
BLIND_VOTE_LOCK_STAKE_OUTPUT = 10;
BLIND_VOTE_OP_RETURN_OUTPUT = 11;
VOTE_REVEAL_UNLOCK_STAKE_OUTPUT = 12;
VOTE_REVEAL_OP_RETURN_OUTPUT = 13;
LOCKUP_OUTPUT = 14;
LOCKUP_OP_RETURN_OUTPUT = 15;
UNLOCK_OUTPUT = 16;
INVALID_OUTPUT = 17;
}

message SpentInfo {
Expand Down Expand Up @@ -1474,6 +1476,7 @@ message Issuance {
int32 chain_height = 2;
int64 amount = 3;
string pub_key = 4;
string issuance_type = 5;
}

message Proposal {
Expand All @@ -1484,11 +1487,12 @@ message Proposal {
string tx_id = 5;
oneof message {
CompensationProposal compensation_proposal = 6;
ChangeParamProposal change_param_proposal = 7;
BondedRoleProposal bonded_role_proposal = 8;
ConfiscateBondProposal confiscate_bond_proposal = 9;
GenericProposal generic_proposal = 10;
RemoveAssetProposal remove_asset_proposal = 11;
ReimbursementProposal reimbursement_proposal = 7;
ChangeParamProposal change_param_proposal = 8;
BondedRoleProposal bonded_role_proposal = 9;
ConfiscateBondProposal confiscate_bond_proposal = 10;
GenericProposal generic_proposal = 11;
RemoveAssetProposal remove_asset_proposal = 12;
}
}

Expand All @@ -1497,6 +1501,11 @@ message CompensationProposal {
string bsq_address = 2;
}

message ReimbursementProposal {
int64 requested_bsq = 1;
string bsq_address = 2;
}

message ChangeParamProposal {
string param = 1; // name of enum
int64 param_value = 2;
Expand Down
50 changes: 29 additions & 21 deletions core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,28 @@ String getWalletAsString(boolean includePrivKeys) {


///////////////////////////////////////////////////////////////////////////////////////////
// CompensationRequest tx
// Proposal txs
///////////////////////////////////////////////////////////////////////////////////////////

public Transaction completePreparedCompensationRequestTx(Coin issuanceAmount, Address issuanceAddress, Transaction feeTx, byte[] opReturnData) throws
TransactionVerificationException, WalletException, InsufficientMoneyException {

public Transaction completePreparedProposalTx(Transaction preparedBurnFeeTx, byte[] opReturnData)
throws WalletException, InsufficientMoneyException, TransactionVerificationException {
return completePreparedProposalTx(preparedBurnFeeTx, opReturnData, null, null);
}

public Transaction completePreparedReimbursementRequestTx(Coin issuanceAmount, Address issuanceAddress, Transaction feeTx, byte[] opReturnData)
throws TransactionVerificationException, WalletException, InsufficientMoneyException {
return completePreparedProposalTx(feeTx, opReturnData, issuanceAmount, issuanceAddress);
}

public Transaction completePreparedCompensationRequestTx(Coin issuanceAmount, Address issuanceAddress, Transaction feeTx, byte[] opReturnData)
throws TransactionVerificationException, WalletException, InsufficientMoneyException {
return completePreparedProposalTx(feeTx, opReturnData, issuanceAmount, issuanceAddress);
}

private Transaction completePreparedProposalTx(Transaction feeTx, byte[] opReturnData,
@Nullable Coin issuanceAmount, @Nullable Address issuanceAddress)
throws TransactionVerificationException, WalletException, InsufficientMoneyException {

// (BsqFee)tx has following structure:
// inputs [1-n] BSQ inputs (fee)
Expand All @@ -160,7 +177,7 @@ public Transaction completePreparedCompensationRequestTx(Coin issuanceAmount, Ad
// inputs [1-n] BSQ inputs for request fee
// inputs [1-n] BTC inputs for BSQ issuance and miner fee
// outputs [1] Mandatory BSQ request fee change output (>= 546 Satoshi)
// outputs [1] Potentially BSQ issuance output (>= 546 Satoshi)
// outputs [1] Potentially BSQ issuance output (>= 546 Satoshi) - in case of a issuance tx, otherwise that output does not exist
// outputs [0-1] BTC change output from issuance and miner fee inputs (>= 546 Satoshi)
// outputs [1] OP_RETURN with opReturnData and amount 0
// mining fee: BTC mining fee + burned BSQ fee
Expand All @@ -174,9 +191,11 @@ public Transaction completePreparedCompensationRequestTx(Coin issuanceAmount, Ad
// BSQ change outputs from BSQ fee inputs.
feeTx.getOutputs().forEach(preparedTx::addOutput);

// BSQ issuance output
preparedTx.addOutput(issuanceAmount, issuanceAddress);

// For generic proposals there is no issuance output, for compensation and reimburse requests there is
if (issuanceAmount != null && issuanceAddress != null) {
// BSQ issuance output
preparedTx.addOutput(issuanceAmount, issuanceAddress);
}

// safety check counter to avoid endless loops
int counter = 0;
Expand Down Expand Up @@ -204,8 +223,8 @@ public Transaction completePreparedCompensationRequestTx(Coin issuanceAmount, Ad
}

Transaction tx = new Transaction(params);
preparedBsqTxInputs.stream().forEach(tx::addInput);
preparedBsqTxOutputs.stream().forEach(tx::addOutput);
preparedBsqTxInputs.forEach(tx::addInput);
preparedBsqTxOutputs.forEach(tx::addOutput);

SendRequest sendRequest = SendRequest.forTx(tx);
sendRequest.shuffleOutputs = false;
Expand All @@ -228,7 +247,7 @@ public Transaction completePreparedCompensationRequestTx(Coin issuanceAmount, Ad

numInputs = resultTx.getInputs().size();
txSizeWithUnsignedInputs = resultTx.bitcoinSerialize().length;
final long estimatedFeeAsLong = txFeePerByte.multiply(txSizeWithUnsignedInputs + sigSizePerInput * numInputs).value;
long estimatedFeeAsLong = txFeePerByte.multiply(txSizeWithUnsignedInputs + sigSizePerInput * numInputs).value;
// calculated fee must be inside of a tolerance range with tx fee
isFeeOutsideTolerance = Math.abs(resultTx.getFee().value - estimatedFeeAsLong) > 1000;
}
Expand All @@ -244,17 +263,6 @@ public Transaction completePreparedCompensationRequestTx(Coin issuanceAmount, Ad
return resultTx;
}

//TODO Similar like completePreparedCompensationRequestTx but without second output for BSQ issuance
public Transaction completePreparedProposalTx(Transaction preparedBurnFeeTx, byte[] opReturnData) {
try {
//TODO dummy
return completePreparedCompensationRequestTx(Coin.valueOf(10000), getFreshAddressEntry().getAddress(),
preparedBurnFeeTx, opReturnData);
} catch (TransactionVerificationException | InsufficientMoneyException | WalletException e) {
e.printStackTrace();
}
throw new RuntimeException("completePreparedGenericProposalTx not implemented yet.");
}

///////////////////////////////////////////////////////////////////////////////////////////
// Blind vote tx
Expand Down
36 changes: 29 additions & 7 deletions core/src/main/java/bisq/core/dao/DaoFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
import bisq.core.dao.governance.proposal.confiscatebond.ConfiscateBondProposalService;
import bisq.core.dao.governance.proposal.generic.GenericProposalService;
import bisq.core.dao.governance.proposal.param.ChangeParamProposalService;
import bisq.core.dao.governance.proposal.reimbursement.ReimbursementConsensus;
import bisq.core.dao.governance.proposal.reimbursement.ReimbursementProposalService;
import bisq.core.dao.governance.proposal.removeAsset.RemoveAssetProposalService;
import bisq.core.dao.governance.proposal.role.BondedRoleProposalService;
import bisq.core.dao.governance.role.BondedRole;
Expand All @@ -54,7 +56,7 @@
import bisq.core.dao.state.blockchain.TxOutput;
import bisq.core.dao.state.blockchain.TxOutputKey;
import bisq.core.dao.state.blockchain.TxType;
import bisq.core.dao.state.governance.Issuance;
import bisq.core.dao.state.governance.IssuanceType;
import bisq.core.dao.state.governance.Param;
import bisq.core.dao.state.period.DaoPhase;
import bisq.core.dao.state.period.PeriodService;
Expand Down Expand Up @@ -104,6 +106,7 @@ public class DaoFacade implements DaoSetupService {
private final MyBlindVoteListService myBlindVoteListService;
private final MyVoteListService myVoteListService;
private final CompensationProposalService compensationProposalService;
private final ReimbursementProposalService reimbursementProposalService;
private final ChangeParamProposalService changeParamProposalService;
private final ConfiscateBondProposalService confiscateBondProposalService;
private final BondedRoleProposalService bondedRoleProposalService;
Expand All @@ -126,6 +129,7 @@ public DaoFacade(MyProposalListService myProposalListService,
MyBlindVoteListService myBlindVoteListService,
MyVoteListService myVoteListService,
CompensationProposalService compensationProposalService,
ReimbursementProposalService reimbursementProposalService,
ChangeParamProposalService changeParamProposalService,
ConfiscateBondProposalService confiscateBondProposalService,
BondedRoleProposalService bondedRoleProposalService,
Expand All @@ -144,6 +148,7 @@ public DaoFacade(MyProposalListService myProposalListService,
this.myBlindVoteListService = myBlindVoteListService;
this.myVoteListService = myVoteListService;
this.compensationProposalService = compensationProposalService;
this.reimbursementProposalService = reimbursementProposalService;
this.changeParamProposalService = changeParamProposalService;
this.confiscateBondProposalService = confiscateBondProposalService;
this.bondedRoleProposalService = bondedRoleProposalService;
Expand Down Expand Up @@ -223,6 +228,15 @@ public ProposalWithTransaction getCompensationProposalWithTransaction(String nam
requestedBsq);
}

public ProposalWithTransaction getReimbursementProposalWithTransaction(String name,
String link,
Coin requestedBsq)
throws ValidationException, InsufficientMoneyException, TxException {
return reimbursementProposalService.createProposalWithTransaction(name,
link,
requestedBsq);
}

public ProposalWithTransaction getParamProposalWithTransaction(String name,
String link,
Param param,
Expand Down Expand Up @@ -517,8 +531,8 @@ public Coin getGenesisTotalSupply() {
return daoStateService.getGenesisTotalSupply();
}

public Set<Issuance> getIssuanceSet() {
return daoStateService.getIssuanceSet();
public int getNumIssuanceTransactions(IssuanceType issuanceType) {
return daoStateService.getIssuanceSet(issuanceType).size();
}

public Set<Tx> getFeeTxs() {
Expand All @@ -541,8 +555,8 @@ public long getTotalBurntFee() {
return daoStateService.getTotalBurntFee();
}

public long getTotalIssuedAmountFromCompRequests() {
return daoStateService.getTotalIssuedAmount();
public long getTotalIssuedAmount(IssuanceType issuanceType) {
return daoStateService.getTotalIssuedAmount(issuanceType);
}

public long getBlockTime(int issuanceBlockHeight) {
Expand All @@ -553,8 +567,8 @@ public int getIssuanceBlockHeight(String txId) {
return daoStateService.getIssuanceBlockHeight(txId);
}

public boolean isIssuanceTx(String txId) {
return daoStateService.isIssuanceTx(txId);
public boolean isIssuanceTx(String txId, IssuanceType issuanceType) {
return daoStateService.isIssuanceTx(txId, issuanceType);
}

public boolean hasTxBurntFee(String hashAsString) {
Expand Down Expand Up @@ -605,6 +619,14 @@ public Coin getMaxCompensationRequestAmount() {
return CompensationConsensus.getMaxCompensationRequestAmount(daoStateService, periodService.getChainHeight());
}

public Coin getMinReimbursementRequestAmount() {
return ReimbursementConsensus.getMinReimbursementRequestAmount(daoStateService, periodService.getChainHeight());
}

public Coin getMaxReimbursementRequestAmount() {
return ReimbursementConsensus.getMaxReimbursementRequestAmount(daoStateService, periodService.getChainHeight());
}

public long getPramValue(Param param) {
return daoStateService.getParamValue(param, periodService.getChainHeight());
}
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/bisq/core/dao/DaoModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
import bisq.core.dao.governance.proposal.generic.GenericProposalValidator;
import bisq.core.dao.governance.proposal.param.ChangeParamProposalService;
import bisq.core.dao.governance.proposal.param.ChangeParamValidator;
import bisq.core.dao.governance.proposal.reimbursement.ReimbursementProposalService;
import bisq.core.dao.governance.proposal.reimbursement.ReimbursementValidator;
import bisq.core.dao.governance.proposal.removeAsset.RemoveAssetProposalService;
import bisq.core.dao.governance.proposal.removeAsset.RemoveAssetValidator;
import bisq.core.dao.governance.proposal.role.BondedRoleProposalService;
Expand Down Expand Up @@ -131,6 +133,9 @@ protected void configure() {
bind(CompensationValidator.class).in(Singleton.class);
bind(CompensationProposalService.class).in(Singleton.class);

bind(ReimbursementValidator.class).in(Singleton.class);
bind(ReimbursementProposalService.class).in(Singleton.class);

bind(ChangeParamValidator.class).in(Singleton.class);
bind(ChangeParamProposalService.class).in(Singleton.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import bisq.core.dao.state.DaoStateListener;
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.blockchain.Block;
import bisq.core.dao.state.governance.IssuanceType;
import bisq.core.dao.state.period.DaoPhase;
import bisq.core.dao.state.period.PeriodService;

Expand Down Expand Up @@ -83,6 +84,8 @@

import javax.annotation.Nullable;

import static com.google.common.base.Preconditions.checkArgument;

/**
* Publishes blind vote tx and blind vote payload to p2p network.
* Maintains myBlindVoteList for own blind votes. Triggers republishing of my blind votes at startup during blind
Expand Down Expand Up @@ -278,8 +281,10 @@ public MeritList getMerits(@Nullable String blindVoteTxId) {
.filter(txId -> periodService.isTxInPastCycle(txId, periodService.getChainHeight()))
.collect(Collectors.toSet());

return new MeritList(daoStateService.getIssuanceSet().stream()
return new MeritList(daoStateService.getIssuanceSet(IssuanceType.COMPENSATION).stream()
.map(issuance -> {
checkArgument(issuance.getIssuanceType() == IssuanceType.COMPENSATION,
"IssuanceType must be COMPENSATION for MeritList");
// We check if it is our proposal
if (!myCompensationProposalTxIs.contains(issuance.getTxId()))
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.blockchain.Tx;
import bisq.core.dao.state.governance.Issuance;
import bisq.core.dao.state.governance.IssuanceType;

import bisq.common.crypto.Encryption;
import bisq.common.util.Utilities;
Expand Down Expand Up @@ -68,8 +69,11 @@ public static long getMeritStake(String blindVoteTxId, MeritList meritList, int
.filter(merit -> isSignatureValid(merit.getSignature(), merit.getIssuance().getPubKey(), blindVoteTxId))
.mapToLong(merit -> {
try {
return getWeightedMeritAmount(merit.getIssuance().getAmount(),
merit.getIssuance().getChainHeight(),
Issuance issuance = merit.getIssuance();
checkArgument(issuance.getIssuanceType() == IssuanceType.COMPENSATION,
"issuance must be of type COMPENSATION");
return getWeightedMeritAmount(issuance.getAmount(),
issuance.getChainHeight(),
txChainHeight,
BLOCKS_PER_YEAR);
} catch (Throwable t) {
Expand Down Expand Up @@ -148,6 +152,7 @@ public static long getCurrentlyAvailableMerit(MeritList meritList, int currentCh
.mapToLong(merit -> {
try {
Issuance issuance = merit.getIssuance();
checkArgument(issuance.getIssuanceType() == IssuanceType.COMPENSATION, "issuance must be of type COMPENSATION");
int issuanceHeight = issuance.getChainHeight();
checkArgument(issuanceHeight <= currentChainHeight,
"issuanceHeight must not be larger as currentChainHeight");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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.governance.proposal;

import org.bitcoinj.core.Coin;

/**
* Marker interface for proposals which can lead to new BSQ issuance
*/
public interface IssuanceProposal {
Coin getRequestedBsq();

String getBsqAddress();

String getTxId();
}
Loading

0 comments on commit 5113ccc

Please sign in to comment.