mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 23:06:39 +01:00
Add bonded reputation
This commit is contained in:
parent
b9d6b3a007
commit
7b72f10eb2
11 changed files with 196 additions and 19 deletions
|
@ -1533,6 +1533,12 @@ message BondedRoleList {
|
|||
repeated BondedRole bonded_role = 1;
|
||||
}
|
||||
|
||||
message BondedReputation {
|
||||
string salt = 1;
|
||||
string lockup_tx_id = 2;
|
||||
string unlock_tx_id = 3;
|
||||
}
|
||||
|
||||
message TempProposalPayload {
|
||||
Proposal proposal = 1;
|
||||
bytes owner_pub_key_encoded = 2;
|
||||
|
|
|
@ -508,8 +508,8 @@ public class DaoFacade implements DaoSetupService {
|
|||
return bondedRolesService.getBondedRoleFromHash(hash);
|
||||
}
|
||||
|
||||
public boolean isUnlocking(BondedRole bondedRole) {
|
||||
return bsqStateService.isUnlocking(bondedRole);
|
||||
public boolean isUnlocking(BondWithHash bondWithHash) {
|
||||
return bsqStateService.isUnlocking(bondWithHash);
|
||||
}
|
||||
|
||||
public Coin getMinCompensationRequestAmount() {
|
||||
|
|
|
@ -89,11 +89,7 @@ public class BondingConsensus {
|
|||
return Arrays.copyOfRange(opReturnData, 5, 25);
|
||||
}
|
||||
|
||||
public static byte[] getHash(LockupType lockupType, BondWithHash bondWithHash) {
|
||||
if (lockupType == LockupType.BONDED_ROLE) {
|
||||
return bondWithHash.getHash();
|
||||
} else {
|
||||
throw new RuntimeException("Trade bonds not implemented yet");
|
||||
}
|
||||
public static byte[] getHash(BondWithHash bondWithHash) {
|
||||
return bondWithHash.getHash();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,5 +18,7 @@
|
|||
package bisq.core.dao.bonding.bond;
|
||||
|
||||
public interface BondWithHash {
|
||||
|
||||
String getUnlockTxId();
|
||||
byte[] getHash();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* 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.bonding.bond;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.state.BsqStateService;
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import bisq.common.crypto.Hash;
|
||||
import bisq.common.proto.network.NetworkPayload;
|
||||
import bisq.common.proto.persistable.PersistablePayload;
|
||||
|
||||
import io.bisq.generated.protobuffer.PB;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class BondedReputation implements PersistablePayload, NetworkPayload, BondWithHash {
|
||||
@Nullable
|
||||
@Setter
|
||||
private final String salt;
|
||||
|
||||
@Setter
|
||||
private String lockupTxId;
|
||||
|
||||
@Nullable
|
||||
@Setter
|
||||
private String unlockTxId;
|
||||
|
||||
public BondedReputation(@Nullable String salt) {
|
||||
this(salt,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
public static BondedReputation createBondedReputation() {
|
||||
return new BondedReputation(UUID.randomUUID().toString());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PROTO BUFFER
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public BondedReputation(String salt,
|
||||
@Nullable String lockupTxId,
|
||||
@Nullable String unlockTxId) {
|
||||
this.salt = salt;
|
||||
this.lockupTxId = lockupTxId;
|
||||
this.unlockTxId = unlockTxId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PB.BondedReputation toProtoMessage() {
|
||||
PB.BondedReputation.Builder builder = PB.BondedReputation.newBuilder()
|
||||
.setSalt(salt);
|
||||
Optional.ofNullable(lockupTxId).ifPresent(builder::setLockupTxId);
|
||||
Optional.ofNullable(unlockTxId).ifPresent(builder::setUnlockTxId);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static BondedReputation fromProto(PB.BondedReputation proto) {
|
||||
return new BondedReputation(proto.getSalt(),
|
||||
proto.getLockupTxId().isEmpty() ? null : proto.getLockupTxId(),
|
||||
proto.getUnlockTxId().isEmpty() ? null : proto.getUnlockTxId());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public String getUnlockTxId() {
|
||||
return unlockTxId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getHash() {
|
||||
// We use the salt as input for the hash
|
||||
byte[] bytes = BigInteger.valueOf(hashCode()).toByteArray();
|
||||
byte[] hash = Hash.getSha256Ripemd160hash(bytes);
|
||||
return hash;
|
||||
}
|
||||
|
||||
public String getDisplayString() {
|
||||
return Res.get("dao.bond.bondedReputation");
|
||||
}
|
||||
|
||||
public boolean isLockedUp() {
|
||||
return lockupTxId != null;
|
||||
}
|
||||
|
||||
public boolean isUnlocked() {
|
||||
return unlockTxId != null;
|
||||
}
|
||||
|
||||
public boolean isUnlocking(DaoFacade daoFacade) {
|
||||
return daoFacade.isUnlocking(this);
|
||||
}
|
||||
|
||||
public boolean isUnlocking(BsqStateService bsqStateService) {
|
||||
return bsqStateService.isUnlocking(this);
|
||||
}
|
||||
|
||||
// We use only the immutable data
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BondedReputation that = (BondedReputation) o;
|
||||
return Objects.equals(salt, that.salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BondedReputation{" +
|
||||
"\n salt='" + salt + '\'' +
|
||||
",\n lockupTxId='" + lockupTxId + '\'' +
|
||||
",\n unlockTxId='" + unlockTxId + '\'' +
|
||||
"\n}";
|
||||
}
|
||||
}
|
|
@ -71,7 +71,7 @@ public class LockupService {
|
|||
lockTime >= BondingConsensus.getMinLockTime(), "lockTime not in rage");
|
||||
try {
|
||||
|
||||
byte[] hash = BondingConsensus.getHash(lockupType, bondWithHash);
|
||||
byte[] hash = BondingConsensus.getHash(bondWithHash);
|
||||
byte[] opReturnData = BondingConsensus.getLockupOpReturnData(lockTime, lockupType, hash);
|
||||
final Transaction lockupTx = getLockupTx(lockupAmount, opReturnData);
|
||||
|
||||
|
|
|
@ -137,6 +137,11 @@ public final class BondedRole implements PersistablePayload, NetworkPayload, Bon
|
|||
// Utils
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getUnlockTxId() {
|
||||
return unlockTxId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getHash() {
|
||||
// We use only the immutable data as input for hash
|
||||
|
|
|
@ -19,6 +19,7 @@ package bisq.core.dao.state;
|
|||
|
||||
import bisq.core.dao.DaoSetupService;
|
||||
import bisq.core.dao.bonding.BondingConsensus;
|
||||
import bisq.core.dao.bonding.bond.BondWithHash;
|
||||
import bisq.core.dao.governance.role.BondedRole;
|
||||
import bisq.core.dao.state.blockchain.Block;
|
||||
import bisq.core.dao.state.blockchain.SpentInfo;
|
||||
|
@ -720,8 +721,8 @@ public class BsqStateService implements DaoSetupService {
|
|||
// txOutput.setTxOutputType(TxOutputType.BTC_OUTPUT);
|
||||
}
|
||||
|
||||
public boolean isUnlocking(BondedRole bondedRole) {
|
||||
Optional<Tx> optionalTx = getTx(bondedRole.getUnlockTxId());
|
||||
public boolean isUnlocking(BondWithHash bondWithHash) {
|
||||
Optional<Tx> optionalTx = getTx(bondWithHash.getUnlockTxId());
|
||||
return optionalTx.isPresent() && isUnlockingOutput(optionalTx.get().getTxOutputs().get(0));
|
||||
}
|
||||
|
||||
|
|
|
@ -1324,6 +1324,8 @@ dao.bond.bondedRoleType.details.link=Link to role description
|
|||
dao.bond.bondedRoleType.details.isSingleton=Can be taken by multiple role holders
|
||||
dao.bond.bondedRoleType.details.blocks={0} blocks
|
||||
|
||||
dao.bond.bondedReputation=Bonded Reputation
|
||||
|
||||
dao.bond.table.header=Bonded roles
|
||||
dao.bond.table.column.header.name=Name
|
||||
dao.bond.table.column.header.linkToAccount=Account
|
||||
|
|
|
@ -26,6 +26,8 @@ import bisq.desktop.util.GUIUtil;
|
|||
|
||||
import bisq.core.btc.setup.WalletsSetup;
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.bonding.bond.BondWithHash;
|
||||
import bisq.core.dao.bonding.bond.BondedReputation;
|
||||
import bisq.core.dao.bonding.lockup.LockupType;
|
||||
import bisq.core.dao.governance.role.BondedRole;
|
||||
import bisq.core.dao.governance.role.BondedRoleType;
|
||||
|
@ -65,12 +67,9 @@ public class BondingViewUtils {
|
|||
this.bsqFormatter = bsqFormatter;
|
||||
}
|
||||
|
||||
public void lockupBondForBondedRole(BondedRole bondedRole, ResultHandler resultHandler) {
|
||||
private void lockupBond(BondWithHash bondWithHash, Coin lockupAmount, int lockupTime, LockupType lockupType,
|
||||
ResultHandler resultHandler) {
|
||||
if (GUIUtil.isReadyForTxBroadcast(p2PService, walletsSetup)) {
|
||||
BondedRoleType bondedRoleType = bondedRole.getBondedRoleType();
|
||||
Coin lockupAmount = Coin.valueOf(bondedRoleType.getRequiredBond());
|
||||
int lockupTime = bondedRoleType.getUnlockTime();
|
||||
LockupType lockupType = LockupType.BONDED_ROLE;
|
||||
new Popup<>().headLine(Res.get("dao.bonding.lock.sendFunds.headline"))
|
||||
.confirmation(Res.get("dao.bonding.lock.sendFunds.details",
|
||||
bsqFormatter.formatCoinWithCode(lockupAmount),
|
||||
|
@ -81,7 +80,7 @@ public class BondingViewUtils {
|
|||
daoFacade.publishLockupTx(lockupAmount,
|
||||
lockupTime,
|
||||
lockupType,
|
||||
bondedRole,
|
||||
bondWithHash,
|
||||
() -> {
|
||||
new Popup<>().feedback(Res.get("dao.tx.published.success")).show();
|
||||
},
|
||||
|
@ -97,6 +96,18 @@ public class BondingViewUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public void lockupBondForBondedRole(BondedRole bondedRole, ResultHandler resultHandler) {
|
||||
BondedRoleType bondedRoleType = bondedRole.getBondedRoleType();
|
||||
Coin lockupAmount = Coin.valueOf(bondedRoleType.getRequiredBond());
|
||||
int lockupTime = bondedRoleType.getUnlockTime();
|
||||
lockupBond(bondedRole, lockupAmount, lockupTime, LockupType.BONDED_ROLE, resultHandler);
|
||||
}
|
||||
|
||||
public void lockupBondForReputation(Coin lockupAmount, int lockupTime, ResultHandler resultHandler) {
|
||||
BondedReputation bondedReputation = BondedReputation.createBondedReputation();
|
||||
lockupBond(bondedReputation, lockupAmount, lockupTime, LockupType.REPUTATION, resultHandler);
|
||||
}
|
||||
|
||||
public void unLock(String lockupTxId) {
|
||||
if (GUIUtil.isReadyForTxBroadcast(p2PService, walletsSetup)) {
|
||||
Optional<TxOutput> lockupTxOutput = daoFacade.getLockupTxOutput(lockupTxId);
|
||||
|
|
|
@ -195,13 +195,18 @@ public class LockupView extends ActivatableView<GridPane, Void> implements BsqBa
|
|||
lockupButton.setOnAction((event) -> {
|
||||
switch (lockupTypeComboBox.getValue()) {
|
||||
case BONDED_ROLE:
|
||||
if (bondedRolesComboBox.getValue() != null ) {
|
||||
if (bondedRolesComboBox.getValue() != null) {
|
||||
bondingViewUtils.lockupBondForBondedRole(bondedRolesComboBox.getValue(),
|
||||
() -> bondedRolesComboBox.getSelectionModel().clearSelection());
|
||||
}
|
||||
break;
|
||||
case REPUTATION:
|
||||
log.error("REPUTATION!!!!!!!!!!!!!");
|
||||
bondingViewUtils.lockupBondForReputation(bsqFormatter.parseToCoin(amountInputTextField.getText()),
|
||||
Integer.parseInt(timeInputTextField.getText()),
|
||||
() -> {
|
||||
amountInputTextField.setText("");
|
||||
timeInputTextField.setText("");
|
||||
});
|
||||
break;
|
||||
default:
|
||||
log.error("Unknown lockup option=" + lockupTypeComboBox.getValue());
|
||||
|
|
Loading…
Add table
Reference in a new issue