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

Verify dao param default vals #1769 #1824

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -59,117 +59,163 @@ public void validateDataFields(Proposal proposal) throws ValidationException {
}
}

// TODO
public void validateParamValue(Param param, long paramValue) throws ChangeParamValidationException {

// max 4 times the current value. min 25% of current value as general boundaries
checkMinMax(param, paramValue, 300, -75);
checkMinMaxForProposedValue(param, paramValue, 4, 4);

switch (param) {
case UNDEFINED:
break;

throw new ChangeParamValidationException(Res.get("validation.paramImmutable"));
case DEFAULT_MAKER_FEE_BSQ:
// max twice the current value and min half of current value as suggested boundaries
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;
case DEFAULT_TAKER_FEE_BSQ:
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;
case MIN_MAKER_FEE_BSQ:
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;
case MIN_TAKER_FEE_BSQ:
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;
case DEFAULT_MAKER_FEE_BTC:
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;
case DEFAULT_TAKER_FEE_BTC:
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;
case MIN_MAKER_FEE_BTC:
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;
case MIN_TAKER_FEE_BTC:
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;

case PROPOSAL_FEE:
checkMinMaxForProposedValue(param, paramValue, 4, 4);
break;
case BLIND_VOTE_FEE:
checkMinMaxForProposedValue(param, paramValue, 4, 4);
break;

case COMPENSATION_REQUEST_MIN_AMOUNT:
case REIMBURSEMENT_MIN_AMOUNT:
if (paramValue < Restrictions.getMinNonDustOutput().value)
throw new ChangeParamValidationException(Res.get("validation.amountBelowDust", Restrictions.getMinNonDustOutput().value));
checkMinMax(param, paramValue, 100, -50);
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;
case COMPENSATION_REQUEST_MAX_AMOUNT:
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;
case REIMBURSEMENT_MIN_AMOUNT:
if (paramValue < Restrictions.getMinNonDustOutput().value) {
throw new ChangeParamValidationException(Res.get("validation.amountBelowDust", Restrictions.getMinNonDustOutput().value));
}
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;
case REIMBURSEMENT_MAX_AMOUNT:
checkMinMax(param, paramValue, 100, -50);
checkMinMaxForProposedValue(param, paramValue, 2, 2);
break;

case QUORUM_COMP_REQUEST:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case QUORUM_REIMBURSEMENT:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case QUORUM_CHANGE_PARAM:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case QUORUM_ROLE:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case QUORUM_CONFISCATION:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case QUORUM_GENERIC:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case QUORUM_REMOVE_ASSET:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;

case THRESHOLD_COMP_REQUEST:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case THRESHOLD_REIMBURSEMENT:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case THRESHOLD_CHANGE_PARAM:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case THRESHOLD_ROLE:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case THRESHOLD_CONFISCATION:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case THRESHOLD_GENERIC:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case THRESHOLD_REMOVE_ASSET:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;

case PHASE_UNDEFINED:
checkMinMaxForProposedValue(param, paramValue, 0, 0);
break;
case PHASE_PROPOSAL:
checkMinMaxForProposedValue(param, paramValue, 1, 1);
break;
case PHASE_BREAK1:
checkMinMaxForProposedValue(param, paramValue, 3, 1);
break;
case PHASE_BLIND_VOTE:
checkMinMaxForProposedValue(param, paramValue, 2, 1);
break;
case PHASE_BREAK2:
checkMinMaxForProposedValue(param, paramValue, 3, 1);
break;
case PHASE_VOTE_REVEAL:
checkMinMaxForProposedValue(param, paramValue, 2, 1);
break;
case PHASE_BREAK3:
checkMinMaxForProposedValue(param, paramValue, 3, 1);
break;
case PHASE_RESULT:
checkMinMaxForProposedValue(param, paramValue, 2, 1);
break;
}
}

private void checkMinMax(Param param, long paramValue, long maxPercentChange, long minPercentChange) throws ChangeParamValidationException {
long max = getNewValueByPercentChange(param, maxPercentChange);
if (paramValue > max)
throw new ChangeParamValidationException(Res.get("validation.inputTooLarge", bsqFormatter.formatParamValue(param, max)));
long min = getNewValueByPercentChange(param, minPercentChange);
if (paramValue < min)
throw new ChangeParamValidationException(Res.get("validation.inputTooSmall", bsqFormatter.formatParamValue(param, min)));
@VisibleForTesting
void checkMinMaxForProposedValue(Param param, long proposedNewValue, long maxFactorChange, long minFactorChange) throws ChangeParamValidationException {
long currentValue = getCurrentValue(param);
validateMinValue(param, currentValue, proposedNewValue, minFactorChange);
validateMaxValue(param, currentValue, proposedNewValue, maxFactorChange);
}

/**
* @param param The param to change
* @param percentChange 100 means 100% more than current value -> 2 times current value. -50 means half of the current value
* @return The new value.
*/
//TODO add test
// TODO use multiplier to make it more intuitive? (4,4) means 4 times current value for max and divided by 4 to get min value)
@VisibleForTesting
long getNewValueByPercentChange(Param param, long percentChange) {
checkArgument(percentChange > -100, "percentChange must be bigger than -100");
return (getCurrentValue(param) * 100 * (100 + percentChange)) / 10000;
void validateMinValue(Param param, long currentValue, long proposedNewValue, long factor) throws ChangeParamValidationException {
if(proposedNewValue==0){
throw new ChangeParamValidationException(Res.get("validation.inputCannotBeZero"));
}
if ((proposedNewValue * factor) < currentValue){
throw new ChangeParamValidationException(Res.get("validation.inputTooSmall",
bsqFormatter.formatParamValue(param,10000/factor))
);
}
}

@VisibleForTesting
void validateMaxValue(Param param, long currentValue, long proposedNewValue, long factor) throws ChangeParamValidationException {
if(proposedNewValue==0){
throw new ChangeParamValidationException(Res.get("validation.inputCannotBeZero"));
}
if (proposedNewValue > (currentValue * factor)){
throw new ChangeParamValidationException(Res.get("validation.inputTooLarge",
bsqFormatter.formatParamValue(param, (10000 * factor)))
);
}
}

private long getCurrentValue(Param param) {
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2401,3 +2401,5 @@ validation.interacETransfer.invalidPhone=Invalid phone number format and not an
validation.inputTooLarge=Input must not be larger than {0}
validation.inputTooSmall=Input has to be larger than {0}
validation.amountBelowDust=The amount below the dust limit of {0} is not allowed.
validation.paramImmutable=This parameter cannot be changed.
validation.inputCannotBeZero=Input cannot be zero.
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package bisq.core.dao.governance.proposal.param;

import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.governance.Param;
import bisq.core.dao.state.period.PeriodService;
import bisq.core.locale.Res;
import bisq.core.util.BsqFormatter;

import bisq.common.proto.persistable.PersistenceProtoResolver;

import java.io.File;

import mockit.Injectable;
import mockit.Tested;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class ChangeParamValidatorTest {

@Rule
public ExpectedException thrown = ExpectedException.none();
// @Tested classes are instantiated automatically when needed in a test case,
// using injection where possible, see http://jmockit.github.io/tutorial/Mocking.html#tested
// To force instantiate earlier, use availableDuringSetup
@Tested(fullyInitialized = true, availableDuringSetup = true)
DaoStateService daoStateService;
@Tested(fullyInitialized = true, availableDuringSetup = true)
PeriodService periodService;
@Tested(fullyInitialized = true, availableDuringSetup = true)
BsqFormatter bsqFormatter;
// @Injectable are mocked resources used to for injecting into @Tested classes
// The naming of these resources doesn't matter, any resource that fits will be used for injection

// Used by bsqStateService
@Injectable
PersistenceProtoResolver persistenceProtoResolver;
@Injectable
File storageDir;
@Injectable
String genesisTxId = "genesisTxId";
@Injectable
Integer genesisBlockHeight = 200;

// Used by periodService
@Injectable
int chainHeight = 400;

@Before
public void setUp() {
Res.setup();
}
//-1
@Test
public void testCheckMinMaxForProposedValueZero() throws ChangeParamValidationException {

Param param = Param.DEFAULT_MAKER_FEE_BSQ;
long proposedNewValue = 0;
long maxFactorChange = 2;
long minFactorChange = 2;

thrown.expect(ChangeParamValidationException.class);
thrown.expectMessage("Input cannot be zero.");
ChangeParamValidator changeParamValidator = new ChangeParamValidator(daoStateService,periodService,bsqFormatter);
changeParamValidator.checkMinMaxForProposedValue(param,proposedNewValue,maxFactorChange,minFactorChange);
}

@Test
public void testCheckMinMaxForProposedValueMin() throws ChangeParamValidationException {

Param param = Param.DEFAULT_MAKER_FEE_BSQ;
long proposedNewValue = 50;
long maxFactorChange = 2;
long minFactorChange = 2;

thrown.expect(ChangeParamValidationException.class);
thrown.expectMessage("Input has to be larger than 50.00%");
ChangeParamValidator changeParamValidator = new ChangeParamValidator(daoStateService,periodService,bsqFormatter);
changeParamValidator.checkMinMaxForProposedValue(param,proposedNewValue,maxFactorChange,minFactorChange);
}

@Test
public void testCheckMinMaxForProposedValueMax() throws ChangeParamValidationException {

Param param = Param.DEFAULT_MAKER_FEE_BSQ;
long proposedNewValue = 450;
long maxFactorChange = 2;
long minFactorChange = 2;

thrown.expect(ChangeParamValidationException.class);
thrown.expectMessage("Input must not be larger than 200.00%");
ChangeParamValidator changeParamValidator = new ChangeParamValidator(daoStateService,periodService,bsqFormatter);
changeParamValidator.checkMinMaxForProposedValue(param,proposedNewValue,maxFactorChange,minFactorChange);
}


@Test
public void testValidateMinValuePos() throws ChangeParamValidationException {

Param param = Param.DEFAULT_MAKER_FEE_BSQ;
long proposedNewValueMinPos = 100;
long minFactorChange = 2;
long currentValue = 200;

ChangeParamValidator changeParamValidator = new ChangeParamValidator(daoStateService,periodService,bsqFormatter);
changeParamValidator.validateMinValue(param,currentValue,proposedNewValueMinPos,minFactorChange);
}

@Test
public void testValidateMinValueNeg() throws ChangeParamValidationException {

Param param = Param.DEFAULT_MAKER_FEE_BSQ;
long proposedNewValueMinNeg = 99;
long minFactorChange = 2;
long currentValue = 200;

thrown.expect(ChangeParamValidationException.class);
thrown.expectMessage("Input has to be larger than 50.00%");
ChangeParamValidator changeParamValidator = new ChangeParamValidator(daoStateService,periodService,bsqFormatter);
changeParamValidator.validateMinValue(param,currentValue,proposedNewValueMinNeg,minFactorChange);
}

@Test
public void testValidateMaxValuePos() throws ChangeParamValidationException {

Param param = Param.DEFAULT_MAKER_FEE_BSQ;
long proposedNewValueMaxPos = 400;
long maxFactorChange = 2;
long currentValue = 200;

ChangeParamValidator changeParamValidator = new ChangeParamValidator(daoStateService,periodService,bsqFormatter);
changeParamValidator.validateMaxValue(param,currentValue,proposedNewValueMaxPos,maxFactorChange);
}

@Test
public void testValidateMaxValueNeg() throws ChangeParamValidationException {

Param param = Param.DEFAULT_MAKER_FEE_BSQ;
long proposedNewValueMaxNeg = 401;
long maxFactorChange = 2;
long currentValue = 200;

thrown.expect(ChangeParamValidationException.class);
thrown.expectMessage("Input must not be larger than 200.00%");
ChangeParamValidator changeParamValidator = new ChangeParamValidator(daoStateService,periodService,bsqFormatter);
changeParamValidator.validateMaxValue(param,currentValue,proposedNewValueMaxNeg,maxFactorChange);

}
}