From bee2d1ebd3c1451194fbe45df1ffb2a44b9dd0ce Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 6 Nov 2018 14:58:12 -0500 Subject: [PATCH] Cleanup bond domain --- .../main/java/bisq/core/dao/DaoFacade.java | 60 ++-- .../main/java/bisq/core/dao/DaoModule.java | 20 +- .../src/main/java/bisq/core/dao/DaoSetup.java | 18 +- .../bisq/core/dao/governance/bond/Bond.java | 30 +- .../dao/governance/bond/BondConsensus.java | 18 +- .../{BondService.java => BondRepository.java} | 286 ++++++++---------- .../core/dao/governance/bond/BondState.java | 13 +- .../core/dao/governance/bond/BondedAsset.java | 2 +- .../dao/governance/bond/ConfiscateBond.java | 63 ---- .../{LockupType.java => LockupReason.java} | 27 +- ...ockupService.java => LockupTxService.java} | 22 +- .../bond/reputation/BondedReputation.java | 3 +- ...e.java => BondedReputationRepository.java} | 41 +-- .../bond/reputation/MyBondedReputation.java | 3 +- ...java => MyBondedReputationRepository.java} | 33 +- .../bond/reputation/MyReputation.java | 7 +- .../bond/reputation/MyReputationList.java | 6 +- .../reputation/MyReputationListService.java | 15 +- .../bond/reputation/Reputation.java | 2 + ...ervice.java => BondedRolesRepository.java} | 40 ++- ...nlockService.java => UnlockTxService.java} | 30 +- .../voteresult/VoteResultService.java | 11 +- .../core/dao/node/parser/OpReturnParser.java | 8 +- .../bisq/core/dao/state/DaoStateService.java | 4 +- .../model/governance/BondedRoleType.java | 10 +- .../resources/i18n/displayStrings.properties | 4 +- .../i18n/displayStrings_de.properties | 4 +- .../i18n/displayStrings_el.properties | 4 +- .../i18n/displayStrings_es.properties | 4 +- .../i18n/displayStrings_fa.properties | 4 +- .../i18n/displayStrings_hu.properties | 4 +- .../i18n/displayStrings_pt.properties | 4 +- .../i18n/displayStrings_ro.properties | 4 +- .../i18n/displayStrings_ru.properties | 4 +- .../i18n/displayStrings_sr.properties | 4 +- .../i18n/displayStrings_th.properties | 4 +- .../i18n/displayStrings_vi.properties | 4 +- .../i18n/displayStrings_zh.properties | 4 +- .../main/dao/bonding/BondingViewUtils.java | 26 +- .../main/dao/bonding/bonds/BondListItem.java | 8 +- .../main/dao/bonding/bonds/BondsView.java | 10 +- 41 files changed, 418 insertions(+), 450 deletions(-) rename core/src/main/java/bisq/core/dao/governance/bond/{BondService.java => BondRepository.java} (75%) delete mode 100644 core/src/main/java/bisq/core/dao/governance/bond/ConfiscateBond.java rename core/src/main/java/bisq/core/dao/governance/bond/lockup/{LockupType.java => LockupReason.java} (67%) rename core/src/main/java/bisq/core/dao/governance/bond/lockup/{LockupService.java => LockupTxService.java} (87%) rename core/src/main/java/bisq/core/dao/governance/bond/reputation/{BondedReputationService.java => BondedReputationRepository.java} (71%) rename core/src/main/java/bisq/core/dao/governance/bond/reputation/{MyBondedReputationService.java => MyBondedReputationRepository.java} (75%) rename core/src/main/java/bisq/core/dao/governance/bond/role/{BondedRolesService.java => BondedRolesRepository.java} (65%) rename core/src/main/java/bisq/core/dao/governance/bond/unlock/{UnlockService.java => UnlockTxService.java} (79%) diff --git a/core/src/main/java/bisq/core/dao/DaoFacade.java b/core/src/main/java/bisq/core/dao/DaoFacade.java index 0bc623c46a..428d479965 100644 --- a/core/src/main/java/bisq/core/dao/DaoFacade.java +++ b/core/src/main/java/bisq/core/dao/DaoFacade.java @@ -25,16 +25,16 @@ import bisq.core.dao.governance.ballot.BallotListService; import bisq.core.dao.governance.blindvote.BlindVoteConsensus; import bisq.core.dao.governance.blindvote.MyBlindVoteListService; import bisq.core.dao.governance.bond.Bond; -import bisq.core.dao.governance.bond.lockup.LockupService; -import bisq.core.dao.governance.bond.lockup.LockupType; +import bisq.core.dao.governance.bond.lockup.LockupReason; +import bisq.core.dao.governance.bond.lockup.LockupTxService; import bisq.core.dao.governance.bond.reputation.BondedReputation; -import bisq.core.dao.governance.bond.reputation.BondedReputationService; +import bisq.core.dao.governance.bond.reputation.BondedReputationRepository; import bisq.core.dao.governance.bond.reputation.MyBondedReputation; -import bisq.core.dao.governance.bond.reputation.MyBondedReputationService; +import bisq.core.dao.governance.bond.reputation.MyBondedReputationRepository; import bisq.core.dao.governance.bond.reputation.MyReputationListService; import bisq.core.dao.governance.bond.role.BondedRole; -import bisq.core.dao.governance.bond.role.BondedRolesService; -import bisq.core.dao.governance.bond.unlock.UnlockService; +import bisq.core.dao.governance.bond.role.BondedRolesRepository; +import bisq.core.dao.governance.bond.unlock.UnlockTxService; import bisq.core.dao.governance.myvote.MyVote; import bisq.core.dao.governance.myvote.MyVoteListService; import bisq.core.dao.governance.param.Param; @@ -119,12 +119,12 @@ public class DaoFacade implements DaoSetupService { private final RoleProposalFactory roleProposalFactory; private final GenericProposalFactory genericProposalFactory; private final RemoveAssetProposalFactory removeAssetProposalFactory; - private final BondedRolesService bondedRolesService; - private final BondedReputationService bondedReputationService; + private final BondedRolesRepository bondedRolesRepository; + private final BondedReputationRepository bondedReputationRepository; private final MyReputationListService myReputationListService; - private final MyBondedReputationService myBondedReputationService; - private final LockupService lockupService; - private final UnlockService unlockService; + private final MyBondedReputationRepository myBondedReputationRepository; + private final LockupTxService lockupTxService; + private final UnlockTxService unlockTxService; private final DaoStateStorageService daoStateStorageService; private final ObjectProperty phaseProperty = new SimpleObjectProperty<>(DaoPhase.Phase.UNDEFINED); @@ -145,12 +145,12 @@ public class DaoFacade implements DaoSetupService { RoleProposalFactory roleProposalFactory, GenericProposalFactory genericProposalFactory, RemoveAssetProposalFactory removeAssetProposalFactory, - BondedRolesService bondedRolesService, - BondedReputationService bondedReputationService, + BondedRolesRepository bondedRolesRepository, + BondedReputationRepository bondedReputationRepository, MyReputationListService myReputationListService, - MyBondedReputationService myBondedReputationService, - LockupService lockupService, - UnlockService unlockService, + MyBondedReputationRepository myBondedReputationRepository, + LockupTxService lockupTxService, + UnlockTxService unlockTxService, DaoStateStorageService daoStateStorageService) { this.proposalListPresentation = proposalListPresentation; this.ballotListService = ballotListService; @@ -167,12 +167,12 @@ public class DaoFacade implements DaoSetupService { this.roleProposalFactory = roleProposalFactory; this.genericProposalFactory = genericProposalFactory; this.removeAssetProposalFactory = removeAssetProposalFactory; - this.bondedRolesService = bondedRolesService; - this.bondedReputationService = bondedReputationService; + this.bondedRolesRepository = bondedRolesRepository; + this.bondedReputationRepository = bondedReputationRepository; this.myReputationListService = myReputationListService; - this.myBondedReputationService = myBondedReputationService; - this.lockupService = lockupService; - this.unlockService = unlockService; + this.myBondedReputationRepository = myBondedReputationRepository; + this.lockupTxService = lockupTxService; + this.unlockTxService = unlockTxService; this.daoStateStorageService = daoStateStorageService; } @@ -292,7 +292,7 @@ public class DaoFacade implements DaoSetupService { } public List getBondedRoles() { - return bondedRolesService.getBonds(); + return bondedRolesRepository.getBonds(); } // Show fee @@ -492,14 +492,14 @@ public class DaoFacade implements DaoSetupService { // Use case: Bonding /////////////////////////////////////////////////////////////////////////////////////////// - public void publishLockupTx(Coin lockupAmount, int lockTime, LockupType lockupType, byte[] hash, + public void publishLockupTx(Coin lockupAmount, int lockTime, LockupReason lockupReason, byte[] hash, Consumer resultHandler, ExceptionHandler exceptionHandler) { - lockupService.publishLockupTx(lockupAmount, lockTime, lockupType, hash, resultHandler, exceptionHandler); + lockupTxService.publishLockupTx(lockupAmount, lockTime, lockupReason, hash, resultHandler, exceptionHandler); } public void publishUnlockTx(String lockupTxId, Consumer resultHandler, ExceptionHandler exceptionHandler) { - unlockService.publishUnlockTx(lockupTxId, resultHandler, exceptionHandler); + unlockTxService.publishUnlockTx(lockupTxId, resultHandler, exceptionHandler); } public long getTotalLockupAmount() { @@ -519,19 +519,19 @@ public class DaoFacade implements DaoSetupService { } public List getActiveBondedRoles() { - return bondedRolesService.getActiveBonds(); + return bondedRolesRepository.getActiveBonds(); } public List getAllBonds() { - List bondedReputations = bondedReputationService.getAllBonds(); - List bondedRoles = bondedRolesService.getAllBonds(); + List bondedReputations = bondedReputationRepository.getBonds(); + List bondedRoles = bondedRolesRepository.getBonds(); List bonds = new ArrayList<>(bondedReputations); bonds.addAll(bondedRoles); return bonds; } public List getMyBondedReputations() { - return myBondedReputationService.getMyBondedReputations(); + return myBondedReputationRepository.getMyBondedReputations(); } @@ -661,7 +661,7 @@ public class DaoFacade implements DaoSetupService { } public boolean isMyRole(Role role) { - return bondedRolesService.isMyRole(role); + return bondedRolesRepository.isMyRole(role); } public Optional getBondByLockupTxId(String lockupTxId) { diff --git a/core/src/main/java/bisq/core/dao/DaoModule.java b/core/src/main/java/bisq/core/dao/DaoModule.java index f29f582ac1..42416c9714 100644 --- a/core/src/main/java/bisq/core/dao/DaoModule.java +++ b/core/src/main/java/bisq/core/dao/DaoModule.java @@ -26,12 +26,12 @@ import bisq.core.dao.governance.blindvote.MyBlindVoteListService; import bisq.core.dao.governance.blindvote.network.RepublishGovernanceDataHandler; import bisq.core.dao.governance.blindvote.storage.BlindVoteStorageService; import bisq.core.dao.governance.blindvote.storage.BlindVoteStore; -import bisq.core.dao.governance.bond.lockup.LockupService; -import bisq.core.dao.governance.bond.reputation.BondedReputationService; -import bisq.core.dao.governance.bond.reputation.MyBondedReputationService; +import bisq.core.dao.governance.bond.lockup.LockupTxService; +import bisq.core.dao.governance.bond.reputation.BondedReputationRepository; +import bisq.core.dao.governance.bond.reputation.MyBondedReputationRepository; import bisq.core.dao.governance.bond.reputation.MyReputationListService; -import bisq.core.dao.governance.bond.role.BondedRolesService; -import bisq.core.dao.governance.bond.unlock.UnlockService; +import bisq.core.dao.governance.bond.role.BondedRolesRepository; +import bisq.core.dao.governance.bond.unlock.UnlockTxService; import bisq.core.dao.governance.myvote.MyVoteListService; import bisq.core.dao.governance.period.CycleService; import bisq.core.dao.governance.period.PeriodService; @@ -186,12 +186,12 @@ public class DaoModule extends AppModule { bind(Integer.class).annotatedWith(Names.named(DaoOptionKeys.GENESIS_BLOCK_HEIGHT)).toInstance(genesisBlockHeight); // Bonds - bind(LockupService.class).in(Singleton.class); - bind(UnlockService.class).in(Singleton.class); - bind(BondedRolesService.class).in(Singleton.class); - bind(BondedReputationService.class).in(Singleton.class); + bind(LockupTxService.class).in(Singleton.class); + bind(UnlockTxService.class).in(Singleton.class); + bind(BondedRolesRepository.class).in(Singleton.class); + bind(BondedReputationRepository.class).in(Singleton.class); bind(MyReputationListService.class).in(Singleton.class); - bind(MyBondedReputationService.class).in(Singleton.class); + bind(MyBondedReputationRepository.class).in(Singleton.class); // Asset bind(AssetService.class).in(Singleton.class); diff --git a/core/src/main/java/bisq/core/dao/DaoSetup.java b/core/src/main/java/bisq/core/dao/DaoSetup.java index 438ca7384e..b418d1d535 100644 --- a/core/src/main/java/bisq/core/dao/DaoSetup.java +++ b/core/src/main/java/bisq/core/dao/DaoSetup.java @@ -20,10 +20,10 @@ package bisq.core.dao; import bisq.core.dao.governance.ballot.BallotListService; import bisq.core.dao.governance.blindvote.BlindVoteListService; import bisq.core.dao.governance.blindvote.MyBlindVoteListService; -import bisq.core.dao.governance.bond.reputation.BondedReputationService; -import bisq.core.dao.governance.bond.reputation.MyBondedReputationService; +import bisq.core.dao.governance.bond.reputation.BondedReputationRepository; +import bisq.core.dao.governance.bond.reputation.MyBondedReputationRepository; import bisq.core.dao.governance.bond.reputation.MyReputationListService; -import bisq.core.dao.governance.bond.role.BondedRolesService; +import bisq.core.dao.governance.bond.role.BondedRolesRepository; import bisq.core.dao.governance.period.CycleService; import bisq.core.dao.governance.proposal.ProposalService; import bisq.core.dao.governance.voteresult.MissingDataRequestService; @@ -60,10 +60,10 @@ public class DaoSetup { VoteRevealService voteRevealService, VoteResultService voteResultService, MissingDataRequestService missingDataRequestService, - BondedReputationService bondedReputationService, - BondedRolesService bondedRolesService, + BondedReputationRepository bondedReputationRepository, + BondedRolesRepository bondedRolesRepository, MyReputationListService myReputationListService, - MyBondedReputationService myBondedReputationService, + MyBondedReputationRepository myBondedReputationRepository, DaoFacade daoFacade, ExportJsonFilesService exportJsonFilesService) { @@ -79,10 +79,10 @@ public class DaoSetup { daoSetupServices.add(voteRevealService); daoSetupServices.add(voteResultService); daoSetupServices.add(missingDataRequestService); - daoSetupServices.add(bondedReputationService); - daoSetupServices.add(bondedRolesService); + daoSetupServices.add(bondedReputationRepository); + daoSetupServices.add(bondedRolesRepository); daoSetupServices.add(myReputationListService); - daoSetupServices.add(myBondedReputationService); + daoSetupServices.add(myBondedReputationRepository); daoSetupServices.add(daoFacade); daoSetupServices.add(exportJsonFilesService); daoSetupServices.add(bsqNodeProvider.getBsqNode()); diff --git a/core/src/main/java/bisq/core/dao/governance/bond/Bond.java b/core/src/main/java/bisq/core/dao/governance/bond/Bond.java index adbe0ce456..d4c8cd5df6 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/Bond.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/Bond.java @@ -17,7 +17,7 @@ package bisq.core.dao.governance.bond; -import bisq.core.locale.Res; +import java.util.Objects; import lombok.Getter; import lombok.Setter; @@ -25,7 +25,7 @@ import lombok.Setter; import javax.annotation.Nullable; /** - * Base class for BondedRole and BondedAsset. Holds the bond state of the bonded asset. + * Base class for BondedRole and BondedReputation. Holds the state of the bonded asset. */ @Getter public abstract class Bond { @@ -48,8 +48,7 @@ public abstract class Bond { @Setter private int lockTime; - - public Bond(T bondedAsset) { + protected Bond(T bondedAsset) { this.bondedAsset = bondedAsset; } @@ -58,8 +57,26 @@ public abstract class Bond { bondState != BondState.UNLOCKED; } - public String getDisplayString() { - return Res.get("dao.bonding.info", lockupTxId, getBondedAsset().getDisplayString()); + // Enums must not be used directly for hashCode or equals as it delivers the Object.hashCode (internal address)! + // The equals and hashCode methods cannot be overwritten in Enums. + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Bond)) return false; + Bond bond = (Bond) o; + return amount == bond.amount && + lockupDate == bond.lockupDate && + unlockDate == bond.unlockDate && + lockTime == bond.lockTime && + Objects.equals(bondedAsset, bond.bondedAsset) && + Objects.equals(lockupTxId, bond.lockupTxId) && + Objects.equals(unlockTxId, bond.unlockTxId) && + bondState.name().equals(bond.bondState.name()); + } + + @Override + public int hashCode() { + return Objects.hash(bondedAsset, lockupTxId, unlockTxId, bondState.name(), amount, lockupDate, unlockDate, lockTime); } @Override @@ -72,6 +89,7 @@ public abstract class Bond { ",\n amount=" + amount + ",\n lockupDate=" + lockupDate + ",\n unlockDate=" + unlockDate + + ",\n lockTime=" + lockTime + "\n}"; } } diff --git a/core/src/main/java/bisq/core/dao/governance/bond/BondConsensus.java b/core/src/main/java/bisq/core/dao/governance/bond/BondConsensus.java index 820a9c13ca..25fd40deec 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/BondConsensus.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/BondConsensus.java @@ -17,7 +17,7 @@ package bisq.core.dao.governance.bond; -import bisq.core.dao.governance.bond.lockup.LockupType; +import bisq.core.dao.governance.bond.lockup.LockupReason; import bisq.core.dao.state.model.blockchain.OpReturnType; import bisq.common.app.Version; @@ -44,13 +44,13 @@ public class BondConsensus { @Getter private static int maxLockTime = 65535; - public static byte[] getLockupOpReturnData(int lockTime, LockupType type, byte[] hash) throws IOException { + public static byte[] getLockupOpReturnData(int lockTime, LockupReason type, byte[] hash) throws IOException { // PushData of <= 4 bytes is converted to int when returned from bitcoind and not handled the way we // require by btcd-cli4j, avoid opReturns with 4 bytes or less try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { outputStream.write(OpReturnType.LOCKUP.getType()); outputStream.write(Version.LOCKUP); - outputStream.write(type.getType()); + outputStream.write(type.getId()); byte[] bytes = Utilities.integerToByteArray(lockTime, 2); outputStream.write(bytes[0]); outputStream.write(bytes[1]); @@ -72,19 +72,19 @@ public class BondConsensus { return Utilities.byteArrayToInteger(Arrays.copyOfRange(opReturnData, 3, 5)); } + public static byte[] getHashFromOpReturnData(byte[] opReturnData) { + return Arrays.copyOfRange(opReturnData, 5, 25); + } + public static boolean isLockTimeInValidRange(int lockTime) { return lockTime >= BondConsensus.getMinLockTime() && lockTime <= BondConsensus.getMaxLockTime(); } - public static Optional getLockupType(byte[] opReturnData) { - return LockupType.getLockupType(opReturnData[2]); + public static Optional getLockupReason(byte[] opReturnData) { + return LockupReason.getLockupReason(opReturnData[2]); } public static boolean isLockTimeOver(long unlockBlockHeight, long currentBlockHeight) { return currentBlockHeight >= unlockBlockHeight; } - - public static byte[] getHashFromOpReturnData(byte[] opReturnData) { - return Arrays.copyOfRange(opReturnData, 5, 25); - } } diff --git a/core/src/main/java/bisq/core/dao/governance/bond/BondService.java b/core/src/main/java/bisq/core/dao/governance/bond/BondRepository.java similarity index 75% rename from core/src/main/java/bisq/core/dao/governance/bond/BondService.java rename to core/src/main/java/bisq/core/dao/governance/bond/BondRepository.java index 9cfdd6a941..1e9f51f290 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/BondService.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/BondRepository.java @@ -40,95 +40,21 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkArgument; - /** - * Manages bonds. + * Collect bonds and bond asset data from other sources and provides access to the collection. */ @Slf4j -public abstract class BondService implements DaoStateListener, DaoSetupService { - protected final DaoStateService daoStateService; - protected final BsqWalletService bsqWalletService; - - // This map is just for convenience. The data which are used to fill the map are stored in the DaoState (role, txs). - protected final Map bondByUidMap = new HashMap<>(); - +public abstract class BondRepository implements DaoStateListener, DaoSetupService { /////////////////////////////////////////////////////////////////////////////////////////// - // Constructor + // Static /////////////////////////////////////////////////////////////////////////////////////////// - @Inject - public BondService(DaoStateService daoStateService, BsqWalletService bsqWalletService) { - this.daoStateService = daoStateService; - this.bsqWalletService = bsqWalletService; - - daoStateService.addBsqStateListener(this); - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // DaoSetupService - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void addListeners() { - } - - @Override - public void start() { - updateMap(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // DaoStateListener - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void onNewBlockHeight(int blockHeight) { - } - - @Override - public void onParseTxsComplete(Block block) { - // TODO optimize to not re-write the whole map at each block - updateMap(); - } - - protected void updateMap() { - getBondedAssetStream().forEach(bondedAsset -> { - String uid = bondedAsset.getUid(); - bondByUidMap.putIfAbsent(uid, createBond(bondedAsset)); - T bond = bondByUidMap.get(uid); - - daoStateService.getLockupTxOutputs().forEach(lockupTxOutput -> { - updateBond(bond, bondedAsset, lockupTxOutput); - }); - }); - - updateBondStateFromUnconfirmedLockupTxs(); - updateBondStateFromUnconfirmedUnlockTxs(); - } - - public void updateBond(T bond, R bondedAsset, TxOutput lockupTxOutput) { - // Lets see if we have a lock up tx. - String lockupTxId = lockupTxOutput.getTxId(); - daoStateService.getTx(lockupTxId).ifPresent(lockupTx -> { - byte[] opReturnData = lockupTx.getLastTxOutput().getOpReturnData(); - // We used the hash of th bonded bondedAsset object as our hash in OpReturn of the lock up tx to have a - // unique binding of the tx to the data object. - byte[] hash = BondConsensus.getHashFromOpReturnData(opReturnData); - Optional candidate = findBondedAssetByHash(hash); - if (candidate.isPresent() && bondedAsset.equals(candidate.get())) - applyBondState(daoStateService, bond, lockupTx, lockupTxOutput); - }); - } - public static void applyBondState(DaoStateService daoStateService, Bond bond, Tx lockupTx, TxOutput lockupTxOutput) { if (bond.getBondState() != BondState.LOCKUP_TX_PENDING || bond.getBondState() != BondState.UNLOCK_TX_PENDING) bond.setBondState(BondState.LOCKUP_TX_CONFIRMED); @@ -166,89 +92,6 @@ public abstract class BondService impleme } } - protected abstract T createBond(R bondedAsset); - - @Override - public void onParseBlockChainComplete() { - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // API - /////////////////////////////////////////////////////////////////////////////////////////// - - public List getBonds() { - return new ArrayList<>(bondByUidMap.values()); - } - - public List getActiveBonds() { - return bondByUidMap.values().stream() - .filter(T::isActive) - .collect(Collectors.toList()); - } - - public List getAllBonds() { - return new ArrayList<>(bondByUidMap.values()); - } - - public Optional findBondByLockupTxId(String lockupTxId) { - return bondByUidMap.values().stream() - .filter(bond -> lockupTxId.equals(bond.getLockupTxId())) - .findAny(); - } - - public boolean wasBondedAssetAlreadyBonded(R bondedAsset) { - T bond = bondByUidMap.get(bondedAsset.getUid()); - checkArgument(bond != null, "bond must not be null"); - return bond.getLockupTxId() != null; - } - - public Optional findBondedAssetByHash(byte[] hash) { - return getBondedAssetStream() - .filter(bondedAsset -> Arrays.equals(bondedAsset.getHash(), hash)) - .findAny(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Protected - /////////////////////////////////////////////////////////////////////////////////////////// - - abstract protected Stream getBondedAssetStream(); - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Private - /////////////////////////////////////////////////////////////////////////////////////////// - - private void updateBondStateFromUnconfirmedLockupTxs() { - getBondedAssetStream().filter(bondedAsset -> isLockupTxUnconfirmed(bsqWalletService, bondedAsset)) - .map(bondedAsset -> bondByUidMap.get(bondedAsset.getUid())) - .filter(bond -> bond.getBondState() == BondState.READY_FOR_LOCKUP) - .forEach(bond -> { - if ((bond.getLockupTxId() != null && daoStateService.isConfiscatedLockupTxOutput(bond.getLockupTxId())) || - (bond.getUnlockTxId() != null && daoStateService.isConfiscatedUnlockTxOutput(bond.getUnlockTxId()))) { - bond.setBondState(BondState.CONFISCATED); - } else { - bond.setBondState(BondState.LOCKUP_TX_PENDING); - } - }); - } - - private void updateBondStateFromUnconfirmedUnlockTxs() { - getBondedAssetStream().filter(bondedAsset -> isUnlockTxUnconfirmed(bsqWalletService, daoStateService, bondedAsset)) - .map(bondedAsset -> bondByUidMap.get(bondedAsset.getUid())) - .filter(bond -> bond.getBondState() == BondState.LOCKUP_TX_CONFIRMED) - .forEach(bond -> { - if ((bond.getLockupTxId() != null && daoStateService.isConfiscatedLockupTxOutput(bond.getLockupTxId())) || - (bond.getUnlockTxId() != null && daoStateService.isConfiscatedUnlockTxOutput(bond.getUnlockTxId()))) { - bond.setBondState(BondState.CONFISCATED); - } else { - bond.setBondState(BondState.UNLOCK_TX_PENDING); - } - }); - } - public static boolean isLockupTxUnconfirmed(BsqWalletService bsqWalletService, BondedAsset bondedAsset) { return bsqWalletService.getPendingWalletTransactionsStream() .map(transaction -> transaction.getOutputs().get(transaction.getOutputs().size() - 1)) @@ -274,4 +117,127 @@ public abstract class BondService impleme .map(BaseTxOutput::getOpReturnData) .anyMatch(data -> Arrays.equals(BondConsensus.getHashFromOpReturnData(data), bondedAsset.getHash())); } + + public static boolean isConfiscated(Bond bond, DaoStateService daoStateService) { + return (bond.getLockupTxId() != null && daoStateService.isConfiscatedLockupTxOutput(bond.getLockupTxId())) || + (bond.getUnlockTxId() != null && daoStateService.isConfiscatedUnlockTxOutput(bond.getUnlockTxId())); + } + + + protected final DaoStateService daoStateService; + protected final BsqWalletService bsqWalletService; + + // This map is just for convenience. The data which are used to fill the map are stored in the DaoState (role, txs). + protected final Map bondByUidMap = new HashMap<>(); + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + /////////////////////////////////////////////////////////////////////////////////////////// + + @Inject + public BondRepository(DaoStateService daoStateService, BsqWalletService bsqWalletService) { + this.daoStateService = daoStateService; + this.bsqWalletService = bsqWalletService; + + daoStateService.addBsqStateListener(this); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // DaoSetupService + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void addListeners() { + } + + @Override + public void start() { + updateMap(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // DaoStateListener + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void onNewBlockHeight(int blockHeight) { + } + + @Override + public void onParseTxsComplete(Block block) { + // TODO optimize to not re-write the whole map at each block + updateMap(); + } + + @Override + public void onParseBlockChainComplete() { + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // API + /////////////////////////////////////////////////////////////////////////////////////////// + + public List getBonds() { + return new ArrayList<>(bondByUidMap.values()); + } + + public List getActiveBonds() { + return bondByUidMap.values().stream() + .filter(T::isActive) + .collect(Collectors.toList()); + } + + public boolean isBondedAssetAlreadyInBond(R bondedAsset) { + boolean contains = bondByUidMap.containsKey(bondedAsset.getUid()); + return contains && bondByUidMap.get(bondedAsset.getUid()).getLockupTxId() != null; + + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Protected + /////////////////////////////////////////////////////////////////////////////////////////// + + abstract protected T createBond(R bondedAsset); + + abstract protected void updateBond(T bond, R bondedAsset, TxOutput lockupTxOutput); + + abstract protected Stream getBondedAssetStream(); + + protected void updateMap() { + getBondedAssetStream().forEach(bondedAsset -> { + String uid = bondedAsset.getUid(); + bondByUidMap.putIfAbsent(uid, createBond(bondedAsset)); + T bond = bondByUidMap.get(uid); + + daoStateService.getLockupTxOutputs().forEach(lockupTxOutput -> { + updateBond(bond, bondedAsset, lockupTxOutput); + }); + }); + + updateBondStateFromUnconfirmedLockupTxs(); + updateBondStateFromUnconfirmedUnlockTxs(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Private + /////////////////////////////////////////////////////////////////////////////////////////// + + private void updateBondStateFromUnconfirmedLockupTxs() { + getBondedAssetStream().filter(bondedAsset -> isLockupTxUnconfirmed(bsqWalletService, bondedAsset)) + .map(bondedAsset -> bondByUidMap.get(bondedAsset.getUid())) + .filter(bond -> bond.getBondState() == BondState.READY_FOR_LOCKUP) + .forEach(bond -> bond.setBondState(isConfiscated(bond, daoStateService) ? BondState.CONFISCATED : BondState.LOCKUP_TX_PENDING)); + } + + private void updateBondStateFromUnconfirmedUnlockTxs() { + getBondedAssetStream().filter(bondedAsset -> isUnlockTxUnconfirmed(bsqWalletService, daoStateService, bondedAsset)) + .map(bondedAsset -> bondByUidMap.get(bondedAsset.getUid())) + .filter(bond -> bond.getBondState() == BondState.LOCKUP_TX_CONFIRMED) + .forEach(bond -> bond.setBondState(isConfiscated(bond, daoStateService) ? BondState.CONFISCATED : BondState.UNLOCK_TX_PENDING)); + } } diff --git a/core/src/main/java/bisq/core/dao/governance/bond/BondState.java b/core/src/main/java/bisq/core/dao/governance/bond/BondState.java index 3284366137..1d74ed1996 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/BondState.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/BondState.java @@ -17,14 +17,17 @@ package bisq.core.dao.governance.bond; -// Used in string properties ("dao.bond.bondState.*") +/** + * Holds the different states of a bond. + * Used also in string properties ("dao.bond.bondState.*") + */ public enum BondState { - READY_FOR_LOCKUP, // Accepted by voting but no lockup tx made yet. + READY_FOR_LOCKUP, // Accepted by voting (if role) but no lockup tx made yet. LOCKUP_TX_PENDING, // Tx broadcasted but not confirmed. Used only by tx publisher. LOCKUP_TX_CONFIRMED, UNLOCK_TX_PENDING, // Tx broadcasted but not confirmed. Used only by tx publisher. UNLOCK_TX_CONFIRMED, - UNLOCKING, // lock time not expired - UNLOCKED, - CONFISCATED + UNLOCKING, // Lock time still not expired + UNLOCKED, // Fully unlocked + CONFISCATED // Bond got confiscated by DAO voting } diff --git a/core/src/main/java/bisq/core/dao/governance/bond/BondedAsset.java b/core/src/main/java/bisq/core/dao/governance/bond/BondedAsset.java index 78689cc177..46f5a7c573 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/BondedAsset.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/BondedAsset.java @@ -18,7 +18,7 @@ package bisq.core.dao.governance.bond; /** - * Interface of the bonded asset like the Role or Reputation. + * Represents the bonded asset (e.g. Role or Reputation). */ public interface BondedAsset { byte[] getHash(); diff --git a/core/src/main/java/bisq/core/dao/governance/bond/ConfiscateBond.java b/core/src/main/java/bisq/core/dao/governance/bond/ConfiscateBond.java deleted file mode 100644 index 382e0e7a7c..0000000000 --- a/core/src/main/java/bisq/core/dao/governance/bond/ConfiscateBond.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 . - */ - -package bisq.core.dao.governance.bond; - -import bisq.common.proto.persistable.PersistablePayload; - -import io.bisq.generated.protobuffer.PB; - -import lombok.Value; - -import javax.annotation.concurrent.Immutable; - -/** - * Holds the hash of a confiscated bond. - */ -@Immutable -@Value -public class ConfiscateBond implements PersistablePayload { - private final String lockupTxId; - - public ConfiscateBond(String lockupTxId) { - this.lockupTxId = lockupTxId; - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // PROTO BUFFER - /////////////////////////////////////////////////////////////////////////////////////////// - - - @Override - public PB.ConfiscateBond toProtoMessage() { - return PB.ConfiscateBond.newBuilder() - .setLockupTxId(lockupTxId) - .build(); - } - - public static ConfiscateBond fromProto(PB.ConfiscateBond proto) { - return new ConfiscateBond(proto.getLockupTxId()); - } - - - @Override - public String toString() { - return "ConfiscateBond{" + - "\n lockupTxId='" + lockupTxId + '\'' + - "\n}"; - } -} diff --git a/core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupType.java b/core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupReason.java similarity index 67% rename from core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupType.java rename to core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupReason.java index 914ad31be6..abf4ecde08 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupType.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupReason.java @@ -17,33 +17,32 @@ package bisq.core.dao.governance.bond.lockup; -import bisq.core.locale.Res; - import java.util.Arrays; import java.util.Optional; import lombok.Getter; -public enum LockupType { +/** + * Reason for locking up a bond. + */ +public enum LockupReason { BONDED_ROLE((byte) 0x01), REPUTATION((byte) 0x02); @Getter - private byte type; + private byte id; - LockupType(byte type) { - this.type = type; + LockupReason(byte id) { + this.id = id; } - public String getDisplayString() { + /* public String getDisplayString() { return Res.get("dao.bond.lockupType." + name()); - } + }*/ - public static Optional getLockupType(byte type) { - return Arrays.stream(LockupType.values()) - .filter(lockupType -> lockupType.type == type) - .map(Optional::of) - .findAny() - .orElse(Optional.empty()); + public static Optional getLockupReason(byte id) { + return Arrays.stream(LockupReason.values()) + .filter(lockupType -> lockupType.id == id) + .findAny(); } } diff --git a/core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupService.java b/core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupTxService.java similarity index 87% rename from core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupService.java rename to core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupTxService.java index bc72fa8c21..d842f4c028 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupService.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/lockup/LockupTxService.java @@ -43,8 +43,11 @@ import lombok.extern.slf4j.Slf4j; import static com.google.common.base.Preconditions.checkArgument; +/** + * Service for publishing the lockup transaction. + */ @Slf4j -public class LockupService { +public class LockupTxService { private final WalletsManager walletsManager; private final BsqWalletService bsqWalletService; private final BtcWalletService btcWalletService; @@ -55,23 +58,22 @@ public class LockupService { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public LockupService(WalletsManager walletsManager, - BsqWalletService bsqWalletService, - BtcWalletService btcWalletService) { + public LockupTxService(WalletsManager walletsManager, + BsqWalletService bsqWalletService, + BtcWalletService btcWalletService) { this.walletsManager = walletsManager; this.bsqWalletService = bsqWalletService; this.btcWalletService = btcWalletService; } - public void publishLockupTx(Coin lockupAmount, int lockTime, LockupType lockupType, byte[] hash, + public void publishLockupTx(Coin lockupAmount, int lockTime, LockupReason lockupReason, byte[] hash, Consumer resultHandler, ExceptionHandler exceptionHandler) { checkArgument(lockTime <= BondConsensus.getMaxLockTime() && - lockTime >= BondConsensus.getMinLockTime(), "lockTime not in rage"); + lockTime >= BondConsensus.getMinLockTime(), "lockTime not in range"); try { - byte[] opReturnData = BondConsensus.getLockupOpReturnData(lockTime, lockupType, hash); + byte[] opReturnData = BondConsensus.getLockupOpReturnData(lockTime, lockupReason, hash); Transaction lockupTx = createLockupTx(lockupAmount, opReturnData); - //noinspection Duplicates walletsManager.publishAndCommitBsqTx(lockupTx, new TxBroadcaster.Callback() { @Override public void onSuccess(Transaction transaction) { @@ -99,6 +101,8 @@ public class LockupService { throws InsufficientMoneyException, WalletException, TransactionVerificationException { Transaction preparedTx = bsqWalletService.getPreparedLockupTx(lockupAmount); Transaction txWithBtcFee = btcWalletService.completePreparedBsqTx(preparedTx, true, opReturnData); - return bsqWalletService.signTx(txWithBtcFee); + Transaction transaction = bsqWalletService.signTx(txWithBtcFee); + log.info("Lockup tx: " + transaction); + return transaction; } } diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/BondedReputation.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/BondedReputation.java index 85053f5ac1..a630672771 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/BondedReputation.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/BondedReputation.java @@ -29,11 +29,10 @@ import lombok.Getter; @EqualsAndHashCode(callSuper = true) public final class BondedReputation extends Bond { - public BondedReputation(Reputation reputation) { + BondedReputation(Reputation reputation) { super(reputation); } - @Override public String toString() { return "BondedReputation{" + diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/BondedReputationService.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/BondedReputationRepository.java similarity index 71% rename from core/src/main/java/bisq/core/dao/governance/bond/reputation/BondedReputationService.java rename to core/src/main/java/bisq/core/dao/governance/bond/reputation/BondedReputationRepository.java index 5e9f195876..c5537c45ad 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/BondedReputationService.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/BondedReputationRepository.java @@ -20,8 +20,8 @@ package bisq.core.dao.governance.bond.reputation; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.dao.governance.bond.Bond; import bisq.core.dao.governance.bond.BondConsensus; -import bisq.core.dao.governance.bond.BondService; -import bisq.core.dao.governance.bond.role.BondedRolesService; +import bisq.core.dao.governance.bond.BondRepository; +import bisq.core.dao.governance.bond.role.BondedRolesRepository; import bisq.core.dao.state.DaoStateService; import bisq.core.dao.state.model.blockchain.TxOutput; @@ -35,20 +35,24 @@ import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; +/** + * Collect bonded reputations from the daoState blockchain data excluding bonded roles + * and provides access to the collection. + */ @Slf4j -public class BondedReputationService extends BondService { - private final BondedRolesService bondedRolesService; +public class BondedReputationRepository extends BondRepository { + private final BondedRolesRepository bondedRolesRepository; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public BondedReputationService(DaoStateService daoStateService, BsqWalletService bsqWalletService, - BondedRolesService bondedRolesService) { + public BondedReputationRepository(DaoStateService daoStateService, BsqWalletService bsqWalletService, + BondedRolesRepository bondedRolesRepository) { super(daoStateService, bsqWalletService); - this.bondedRolesService = bondedRolesService; + this.bondedRolesRepository = bondedRolesRepository; } @@ -69,18 +73,13 @@ public class BondedReputationService extends BondService { - bondByUidMap.put(bondedReputation.getBondedAsset().getUid(), bondedReputation); - }); + getBondedReputationStream().forEach(bondedReputation -> bondByUidMap.put(bondedReputation.getBondedAsset().getUid(), bondedReputation)); } private Stream getBondedReputationStream() { - Set bondedRolesLockupTxIdSet = bondedRolesService.getAllBonds().stream().map(e -> e.getLockupTxId()).collect(Collectors.toSet()); - return daoStateService.getLockupTxOutputs().stream() + return getLockupTxOutputsForBondedReputation() .map(lockupTxOutput -> { String lockupTxId = lockupTxOutput.getTxId(); - // long time = daoStateService.getTx(lockupTxId).map(BaseTx::getTime).orElse(0L); - // lockupTxOutput is first output, but we need the data from the opReturn Optional optionalOpReturnTxOutput = daoStateService.getLockupOpReturnTxOutput(lockupTxId); if (optionalOpReturnTxOutput.isPresent()) { TxOutput opReturnTxOutput = optionalOpReturnTxOutput.get(); @@ -94,16 +93,22 @@ public class BondedReputationService extends BondService !bondedRolesLockupTxIdSet.contains(e.getLockupTxId())); + .filter(Objects::nonNull); + } + + private Stream getLockupTxOutputsForBondedReputation() { + // We exclude bonded roles, so we store those ina lookup set. + Set bondedRolesLockupTxIdSet = bondedRolesRepository.getBonds().stream().map(Bond::getLockupTxId).collect(Collectors.toSet()); + return daoStateService.getLockupTxOutputs().stream() + .filter(e -> !bondedRolesLockupTxIdSet.contains(e.getTxId())); } @Override - public void updateBond(BondedReputation bond, Reputation bondedAsset, TxOutput lockupTxOutput) { + protected void updateBond(BondedReputation bond, Reputation bondedAsset, TxOutput lockupTxOutput) { // Lets see if we have a lock up tx. String lockupTxId = lockupTxOutput.getTxId(); daoStateService.getTx(lockupTxId).ifPresent(lockupTx -> { - applyBondState(daoStateService, bond, lockupTx, lockupTxOutput); + BondRepository.applyBondState(daoStateService, bond, lockupTx, lockupTxOutput); }); } } diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputation.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputation.java index 3c56451080..f9af093c4a 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputation.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputation.java @@ -23,7 +23,8 @@ import lombok.EqualsAndHashCode; import lombok.Getter; /** - * Wrapper for reputation which contains the mutable state of a bonded reputation. Only kept in memory. + * Wrapper for reputation which contains the mutable state of my bonded reputation. Only kept in memory. + * As it carries MyReputation it has access to the private salt data. */ @Getter @EqualsAndHashCode(callSuper = true) diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputationService.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputationRepository.java similarity index 75% rename from core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputationService.java rename to core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputationRepository.java index 2cec71a861..871cac2609 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputationService.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputationRepository.java @@ -20,7 +20,7 @@ package bisq.core.dao.governance.bond.reputation; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.dao.DaoSetupService; import bisq.core.dao.governance.bond.BondConsensus; -import bisq.core.dao.governance.bond.BondService; +import bisq.core.dao.governance.bond.BondRepository; import bisq.core.dao.governance.bond.BondState; import bisq.core.dao.state.DaoStateService; @@ -36,8 +36,11 @@ import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; +/** + * Collect MyBondedReputations from the myReputationListService and provides access to the collection. + */ @Slf4j -public class MyBondedReputationService implements DaoSetupService { +public class MyBondedReputationRepository implements DaoSetupService { private final DaoStateService daoStateService; private final BsqWalletService bsqWalletService; private final MyReputationListService myReputationListService; @@ -48,9 +51,9 @@ public class MyBondedReputationService implements DaoSetupService { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public MyBondedReputationService(DaoStateService daoStateService, - BsqWalletService bsqWalletService, - MyReputationListService myReputationListService) { + public MyBondedReputationRepository(DaoStateService daoStateService, + BsqWalletService bsqWalletService, + MyReputationListService myReputationListService) { this.daoStateService = daoStateService; this.bsqWalletService = bsqWalletService; this.myReputationListService = myReputationListService; @@ -75,25 +78,24 @@ public class MyBondedReputationService implements DaoSetupService { /////////////////////////////////////////////////////////////////////////////////////////// public List getMyBondedReputations() { - // It can be that the same salt/hash is in several lockupTxs, so we use a map to eliminate duplicates by the - // collection algorithm. - Map map = new HashMap<>(); + // It can be that the same salt/hash is in several lockupTxs, so we use the bondByLockupTxIdMap to eliminate + // duplicates by the collection algorithm. + Map bondByLockupTxIdMap = new HashMap<>(); myReputationListService.getMyReputationList().stream() .flatMap(this::getMyBondedReputation) - .forEach(e -> map.putIfAbsent(e.getLockupTxId(), e)); + .forEach(e -> bondByLockupTxIdMap.putIfAbsent(e.getLockupTxId(), e)); - return map.values().stream() + return bondByLockupTxIdMap.values().stream() .peek(myBondedReputation -> { - if ((myBondedReputation.getLockupTxId() != null && daoStateService.isConfiscatedLockupTxOutput(myBondedReputation.getLockupTxId())) || - (myBondedReputation.getUnlockTxId() != null && daoStateService.isConfiscatedUnlockTxOutput(myBondedReputation.getUnlockTxId()))) { + if (BondRepository.isConfiscated(myBondedReputation, daoStateService)) { myBondedReputation.setBondState(BondState.CONFISCATED); } else { // We don't have a UI use case for showing LOCKUP_TX_PENDING yet, but lets keep the code so if needed // its there. - if (BondService.isLockupTxUnconfirmed(bsqWalletService, myBondedReputation.getBondedAsset()) && + if (BondRepository.isLockupTxUnconfirmed(bsqWalletService, myBondedReputation.getBondedAsset()) && myBondedReputation.getBondState() == BondState.READY_FOR_LOCKUP) { myBondedReputation.setBondState(BondState.LOCKUP_TX_PENDING); - } else if (BondService.isUnlockTxUnconfirmed(bsqWalletService, daoStateService, myBondedReputation.getBondedAsset()) && + } else if (BondRepository.isUnlockTxUnconfirmed(bsqWalletService, daoStateService, myBondedReputation.getBondedAsset()) && myBondedReputation.getBondState() == BondState.LOCKUP_TX_CONFIRMED) { myBondedReputation.setBondState(BondState.UNLOCK_TX_PENDING); } @@ -110,9 +112,10 @@ public class MyBondedReputationService implements DaoSetupService { .map(lockupTx -> { byte[] opReturnData = lockupTx.getLastTxOutput().getOpReturnData(); byte[] hash = BondConsensus.getHashFromOpReturnData(opReturnData); + // There could be multiple txs with the same hash, so we collect a stream and not use an optional. if (Arrays.equals(hash, myReputation.getHash())) { MyBondedReputation myBondedReputation = new MyBondedReputation(myReputation); - BondService.applyBondState(daoStateService, myBondedReputation, lockupTx, lockupTxOutput); + BondRepository.applyBondState(daoStateService, myBondedReputation, lockupTx, lockupTxOutput); return myBondedReputation; } else { return null; diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputation.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputation.java index b7311c0a7d..ac40f6cebe 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputation.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputation.java @@ -37,13 +37,18 @@ import lombok.extern.slf4j.Slf4j; import javax.annotation.concurrent.Immutable; +/** + * MyReputation is persisted locally and carries the private salt data. In contrast to Reputation which is the public + * data everyone can derive from the blockchain data (hash in opReturn). + */ @Immutable @Value @Slf4j public final class MyReputation implements PersistablePayload, NetworkPayload, BondedAsset { + // Uid is needed to be sure that 2 objects with the same salt are kept separate. private final String uid; private final byte[] salt; - private final transient byte[] hash; // not persisted as it is derived from salt. Stored for caching purpose only. + private final transient byte[] hash; // Not persisted as it is derived from salt. Stored for caching purpose only. public MyReputation(byte[] salt) { this(UUID.randomUUID().toString(), salt); diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java index e2c1e46d1d..5e426e999a 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java @@ -33,11 +33,11 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) public class MyReputationList extends PersistableList { - public MyReputationList(List list) { + private MyReputationList(List list) { super(list); } - public MyReputationList() { + MyReputationList() { super(); } @@ -51,7 +51,7 @@ public class MyReputationList extends PersistableList { return PB.PersistableEnvelope.newBuilder().setMyReputationList(getBuilder()).build(); } - public PB.MyReputationList.Builder getBuilder() { + private PB.MyReputationList.Builder getBuilder() { return PB.MyReputationList.newBuilder() .addAllMyReputation(getList().stream() .map(MyReputation::toProtoMessage) diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationListService.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationListService.java index d9a07eb068..8d5d39f63d 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationListService.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationListService.java @@ -31,10 +31,14 @@ import java.util.concurrent.CopyOnWriteArrayList; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +/** + * Manages the persistence of myReputation objects. + */ @Slf4j public class MyReputationListService implements PersistedDataHost, DaoSetupService { - public interface MyReputationListChangeListener { + @SuppressWarnings("unused") + interface MyReputationListChangeListener { void onListChanged(List list); } @@ -88,10 +92,6 @@ public class MyReputationListService implements PersistedDataHost, DaoSetupServi // API /////////////////////////////////////////////////////////////////////////////////////////// - public void addListener(MyReputationListChangeListener listener) { - listeners.add(listener); - } - public void addReputation(MyReputation reputation) { if (!myReputationList.contains(reputation)) { myReputationList.add(reputation); @@ -103,6 +103,11 @@ public class MyReputationListService implements PersistedDataHost, DaoSetupServi return myReputationList.getList(); } + @SuppressWarnings("unused") + public void addListener(MyReputationListChangeListener listener) { + listeners.add(listener); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Private diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/Reputation.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/Reputation.java index 1cc5d9c095..e7394604be 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/Reputation.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/Reputation.java @@ -30,6 +30,8 @@ import javax.annotation.concurrent.Immutable; /** * Reputation objects we found on the blockchain. We only know the hash of it. + * In contrast to MyReputation which represents the object we created and contains the + * private salt data. */ @Immutable @Value diff --git a/core/src/main/java/bisq/core/dao/governance/bond/role/BondedRolesService.java b/core/src/main/java/bisq/core/dao/governance/bond/role/BondedRolesRepository.java similarity index 65% rename from core/src/main/java/bisq/core/dao/governance/bond/role/BondedRolesService.java rename to core/src/main/java/bisq/core/dao/governance/bond/role/BondedRolesRepository.java index 86754757b9..21aab0b53f 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/role/BondedRolesService.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/role/BondedRolesRepository.java @@ -18,10 +18,10 @@ package bisq.core.dao.governance.bond.role; import bisq.core.btc.wallet.BsqWalletService; -import bisq.core.dao.governance.bond.Bond; -import bisq.core.dao.governance.bond.BondService; +import bisq.core.dao.governance.bond.BondConsensus; +import bisq.core.dao.governance.bond.BondRepository; import bisq.core.dao.state.DaoStateService; -import bisq.core.dao.state.model.governance.BondedRoleType; +import bisq.core.dao.state.model.blockchain.TxOutput; import bisq.core.dao.state.model.governance.Proposal; import bisq.core.dao.state.model.governance.Role; import bisq.core.dao.state.model.governance.RoleProposal; @@ -30,6 +30,7 @@ import org.bitcoinj.core.Transaction; import javax.inject.Inject; +import java.util.Arrays; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -38,17 +39,17 @@ import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; /** - * Manages bonded roles if they got accepted by voting. + * Collect bonded roles from the evaluatedProposals from the daoState and provides access to the collection. */ @Slf4j -public class BondedRolesService extends BondService { +public class BondedRolesRepository extends BondRepository { /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public BondedRolesService(DaoStateService daoStateService, BsqWalletService bsqWalletService) { + public BondedRolesRepository(DaoStateService daoStateService, BsqWalletService bsqWalletService) { super(daoStateService, bsqWalletService); } @@ -67,12 +68,6 @@ public class BondedRolesService extends BondService { .anyMatch(myWalletTransactionIds::contains); } - public Optional getBondedRoleType(String lockUpTxId) { - return findBondByLockupTxId(lockUpTxId) - .map(Bond::getBondedAsset) - .map(Role::getBondedRoleType); - } - /////////////////////////////////////////////////////////////////////////////////////////// // Protected @@ -88,6 +83,27 @@ public class BondedRolesService extends BondService { return getBondedRoleProposalStream().map(RoleProposal::getRole); } + @Override + protected void updateBond(BondedRole bond, Role bondedAsset, TxOutput lockupTxOutput) { + // Lets see if we have a lock up tx. + String lockupTxId = lockupTxOutput.getTxId(); + daoStateService.getTx(lockupTxId).ifPresent(lockupTx -> { + byte[] opReturnData = lockupTx.getLastTxOutput().getOpReturnData(); + // We used the hash of th bonded bondedAsset object as our hash in OpReturn of the lock up tx to have a + // unique binding of the tx to the data object. + byte[] hash = BondConsensus.getHashFromOpReturnData(opReturnData); + Optional candidate = findBondedAssetByHash(hash); + if (candidate.isPresent() && bondedAsset.equals(candidate.get())) + applyBondState(daoStateService, bond, lockupTx, lockupTxOutput); + }); + } + + private Optional findBondedAssetByHash(byte[] hash) { + return getBondedAssetStream() + .filter(bondedAsset -> Arrays.equals(bondedAsset.getHash(), hash)) + .findAny(); + } + private Stream getBondedRoleProposalStream() { return daoStateService.getEvaluatedProposalList().stream() .filter(evaluatedProposal -> evaluatedProposal.getProposal() instanceof RoleProposal) diff --git a/core/src/main/java/bisq/core/dao/governance/bond/unlock/UnlockService.java b/core/src/main/java/bisq/core/dao/governance/bond/unlock/UnlockTxService.java similarity index 79% rename from core/src/main/java/bisq/core/dao/governance/bond/unlock/UnlockService.java rename to core/src/main/java/bisq/core/dao/governance/bond/unlock/UnlockTxService.java index 4b37e7ebac..4a9c1bc0e6 100644 --- a/core/src/main/java/bisq/core/dao/governance/bond/unlock/UnlockService.java +++ b/core/src/main/java/bisq/core/dao/governance/bond/unlock/UnlockTxService.java @@ -35,12 +35,18 @@ import org.bitcoinj.core.Transaction; import javax.inject.Inject; +import java.util.Optional; import java.util.function.Consumer; import lombok.extern.slf4j.Slf4j; +import static com.google.common.base.Preconditions.checkArgument; + +/** + * Service for publishing the unlock transaction. + */ @Slf4j -public class UnlockService { +public class UnlockTxService { private final WalletsManager walletsManager; private final BsqWalletService bsqWalletService; private final BtcWalletService btcWalletService; @@ -52,23 +58,22 @@ public class UnlockService { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public UnlockService(WalletsManager walletsManager, - BsqWalletService bsqWalletService, - BtcWalletService btcWalletService, - DaoStateService daoStateService) { + public UnlockTxService(WalletsManager walletsManager, + BsqWalletService bsqWalletService, + BtcWalletService btcWalletService, + DaoStateService daoStateService) { this.walletsManager = walletsManager; this.bsqWalletService = bsqWalletService; this.btcWalletService = btcWalletService; this.daoStateService = daoStateService; } - public void publishUnlockTx(String lockupTxId, Consumer resultHandler, - ExceptionHandler exceptionHandler) { + public void publishUnlockTx(String lockupTxId, Consumer resultHandler, ExceptionHandler exceptionHandler) { try { - TxOutput lockupTxOutput = daoStateService.getLockupTxOutput(lockupTxId).get(); - final Transaction unlockTx = getUnlockTx(lockupTxOutput); - - //noinspection Duplicates + Optional optionalLockupTxOutput = daoStateService.getLockupTxOutput(lockupTxId); + checkArgument(optionalLockupTxOutput.isPresent(), "lockupTxOutput must be present"); + TxOutput lockupTxOutput = optionalLockupTxOutput.get(); + Transaction unlockTx = getUnlockTx(lockupTxOutput); walletsManager.publishAndCommitBsqTx(unlockTx, new TxBroadcaster.Callback() { @Override public void onSuccess(Transaction transaction) { @@ -94,8 +99,7 @@ public class UnlockService { throws InsufficientMoneyException, WalletException, TransactionVerificationException { Transaction preparedTx = bsqWalletService.getPreparedUnlockTx(lockupTxOutput); Transaction txWithBtcFee = btcWalletService.completePreparedBsqTx(preparedTx, true, null); - final Transaction transaction = bsqWalletService.signTx(txWithBtcFee); - + Transaction transaction = bsqWalletService.signTx(txWithBtcFee); log.info("Unlock tx: " + transaction); return transaction; } diff --git a/core/src/main/java/bisq/core/dao/governance/voteresult/VoteResultService.java b/core/src/main/java/bisq/core/dao/governance/voteresult/VoteResultService.java index 4e8b37a25e..b0fad9b88a 100644 --- a/core/src/main/java/bisq/core/dao/governance/voteresult/VoteResultService.java +++ b/core/src/main/java/bisq/core/dao/governance/voteresult/VoteResultService.java @@ -25,8 +25,7 @@ import bisq.core.dao.governance.blindvote.BlindVoteConsensus; import bisq.core.dao.governance.blindvote.BlindVoteListService; import bisq.core.dao.governance.blindvote.VoteWithProposalTxId; import bisq.core.dao.governance.blindvote.VoteWithProposalTxIdList; -import bisq.core.dao.governance.bond.ConfiscateBond; -import bisq.core.dao.governance.bond.role.BondedRolesService; +import bisq.core.dao.governance.bond.role.BondedRolesRepository; import bisq.core.dao.governance.merit.MeritConsensus; import bisq.core.dao.governance.period.PeriodService; import bisq.core.dao.governance.proposal.IssuanceProposal; @@ -103,7 +102,7 @@ public class VoteResultService implements DaoStateListener, DaoSetupService { private final PeriodService periodService; private final BallotListService ballotListService; private final BlindVoteListService blindVoteListService; - private final BondedRolesService bondedRolesService; + private final BondedRolesRepository bondedRolesRepository; private final IssuanceService issuanceService; private final AssetService assetService; private final MissingDataRequestService missingDataRequestService; @@ -122,7 +121,7 @@ public class VoteResultService implements DaoStateListener, DaoSetupService { PeriodService periodService, BallotListService ballotListService, BlindVoteListService blindVoteListService, - BondedRolesService bondedRolesService, + BondedRolesRepository bondedRolesRepository, IssuanceService issuanceService, AssetService assetService, MissingDataRequestService missingDataRequestService) { @@ -132,7 +131,7 @@ public class VoteResultService implements DaoStateListener, DaoSetupService { this.periodService = periodService; this.ballotListService = ballotListService; this.blindVoteListService = blindVoteListService; - this.bondedRolesService = bondedRolesService; + this.bondedRolesRepository = bondedRolesRepository; this.issuanceService = issuanceService; this.assetService = assetService; this.missingDataRequestService = missingDataRequestService; @@ -661,7 +660,7 @@ public class VoteResultService implements DaoStateListener, DaoSetupService { acceptedEvaluatedProposals.forEach(evaluatedProposal -> { if (evaluatedProposal.getProposal() instanceof ConfiscateBondProposal) { ConfiscateBondProposal confiscateBondProposal = (ConfiscateBondProposal) evaluatedProposal.getProposal(); - daoStateService.confiscateBond(new ConfiscateBond(confiscateBondProposal.getLockupTxId())); + daoStateService.confiscateBond(confiscateBondProposal.getLockupTxId()); StringBuilder sb = new StringBuilder(); sb.append("\n################################################################################\n"); diff --git a/core/src/main/java/bisq/core/dao/node/parser/OpReturnParser.java b/core/src/main/java/bisq/core/dao/node/parser/OpReturnParser.java index b0dc5a1e19..75355c5fd5 100644 --- a/core/src/main/java/bisq/core/dao/node/parser/OpReturnParser.java +++ b/core/src/main/java/bisq/core/dao/node/parser/OpReturnParser.java @@ -19,7 +19,7 @@ package bisq.core.dao.node.parser; import bisq.core.dao.governance.blindvote.BlindVoteConsensus; import bisq.core.dao.governance.bond.BondConsensus; -import bisq.core.dao.governance.bond.lockup.LockupType; +import bisq.core.dao.governance.bond.lockup.LockupReason; import bisq.core.dao.governance.proposal.ProposalConsensus; import bisq.core.dao.governance.voteresult.VoteResultConsensus; import bisq.core.dao.node.parser.exceptions.InvalidParsingConditionException; @@ -107,9 +107,9 @@ class OpReturnParser { case LOCKUP: if (!BondConsensus.hasOpReturnDataValidLength(opReturnData)) return TxOutputType.INVALID_OUTPUT; - Optional lockupType = BondConsensus.getLockupType(opReturnData); - if (!lockupType.isPresent()) { - log.warn("No lockupType found for lockup tx, opReturnData=" + Utilities.encodeToHex(opReturnData)); + Optional optionalLockupReason = BondConsensus.getLockupReason(opReturnData); + if (!optionalLockupReason.isPresent()) { + log.warn("No lockupReason found for lockup tx, opReturnData=" + Utilities.encodeToHex(opReturnData)); return TxOutputType.INVALID_OUTPUT; } diff --git a/core/src/main/java/bisq/core/dao/state/DaoStateService.java b/core/src/main/java/bisq/core/dao/state/DaoStateService.java index e2fbfb54f3..acee24eb0c 100644 --- a/core/src/main/java/bisq/core/dao/state/DaoStateService.java +++ b/core/src/main/java/bisq/core/dao/state/DaoStateService.java @@ -19,7 +19,6 @@ package bisq.core.dao.state; import bisq.core.dao.DaoSetupService; import bisq.core.dao.governance.bond.BondConsensus; -import bisq.core.dao.governance.bond.ConfiscateBond; import bisq.core.dao.governance.param.Param; import bisq.core.dao.state.model.DaoState; import bisq.core.dao.state.model.blockchain.Block; @@ -742,8 +741,7 @@ public class DaoStateService implements DaoSetupService { } // Confiscate bond - public void confiscateBond(ConfiscateBond confiscateBond) { - String lockupTxId = confiscateBond.getLockupTxId(); + public void confiscateBond(String lockupTxId) { Optional optionalTxOutput = getLockupTxOutput(lockupTxId); if (optionalTxOutput.isPresent()) { TxOutput lockupTxOutput = optionalTxOutput.get(); diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/BondedRoleType.java b/core/src/main/java/bisq/core/dao/state/model/governance/BondedRoleType.java index 97f0e580fb..b7381fa621 100644 --- a/core/src/main/java/bisq/core/dao/state/model/governance/BondedRoleType.java +++ b/core/src/main/java/bisq/core/dao/state/model/governance/BondedRoleType.java @@ -21,10 +21,14 @@ import bisq.core.locale.Res; import lombok.Getter; -// Data here must not be changed as it would break backward compatibility! In case we need to change we need to add a new -// entry and maintain the old one. Once all the role holders of an old deprecated role have revoked the role might get removed. -// Add entry to translation file "dao.bond.bondedRoleType...." +/** + * Data here must not be changed as it would break backward compatibility! In case we need to change we need to add a + * new entry and maintain the old one. Once all the role holders of an old deprecated role have revoked the + * role might get removed. + * + * Add entry to translation file "dao.bond.bondedRoleType...." + */ public enum BondedRoleType { // admins GITHUB_ADMIN(50_000, 60, "https://github.com/bisq-network/roles/issues/16", true), diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index fef82a49aa..603036be59 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -1339,9 +1339,9 @@ dao.bonding.info=Lockup Tx ID: {0} / {1} dao.bonding.reputation.salt.info=Salt: {0} # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.GITHUB_ADMIN=Github admin diff --git a/core/src/main/resources/i18n/displayStrings_de.properties b/core/src/main/resources/i18n/displayStrings_de.properties index 824d039020..e764e977d7 100644 --- a/core/src/main/resources/i18n/displayStrings_de.properties +++ b/core/src/main/resources/i18n/displayStrings_de.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Gesperrte Gelder dao.bonding.dashboard.unlockingAmount=Entsperre Gelder (Warten Sie bis die Sperrzeit vorbei ist): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Gekoppelte Rolle +dao.bond.lockupReason.BONDED_ROLE=Gekoppelte Rolle # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Gekoppeltes Ansehen +dao.bond.lockupReason.REPUTATION=Gekoppeltes Ansehen # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Vermittler # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_el.properties b/core/src/main/resources/i18n/displayStrings_el.properties index b12d93874f..afd3ec597f 100644 --- a/core/src/main/resources/i18n/displayStrings_el.properties +++ b/core/src/main/resources/i18n/displayStrings_el.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds: dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_es.properties b/core/src/main/resources/i18n/displayStrings_es.properties index af4b5862ef..6bcc7307f1 100644 --- a/core/src/main/resources/i18n/displayStrings_es.properties +++ b/core/src/main/resources/i18n/displayStrings_es.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds: dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_fa.properties b/core/src/main/resources/i18n/displayStrings_fa.properties index b04ad16819..7449a1895b 100644 --- a/core/src/main/resources/i18n/displayStrings_fa.properties +++ b/core/src/main/resources/i18n/displayStrings_fa.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds: dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_hu.properties b/core/src/main/resources/i18n/displayStrings_hu.properties index 5d0f417f34..54fd678fb2 100644 --- a/core/src/main/resources/i18n/displayStrings_hu.properties +++ b/core/src/main/resources/i18n/displayStrings_hu.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds: dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_pt.properties b/core/src/main/resources/i18n/displayStrings_pt.properties index b881a6def4..d82f3316b2 100644 --- a/core/src/main/resources/i18n/displayStrings_pt.properties +++ b/core/src/main/resources/i18n/displayStrings_pt.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds: dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_ro.properties b/core/src/main/resources/i18n/displayStrings_ro.properties index 9e5439f20f..45d61c6983 100644 --- a/core/src/main/resources/i18n/displayStrings_ro.properties +++ b/core/src/main/resources/i18n/displayStrings_ro.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds: dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_ru.properties b/core/src/main/resources/i18n/displayStrings_ru.properties index 7871b5d3ad..3260caafe5 100644 --- a/core/src/main/resources/i18n/displayStrings_ru.properties +++ b/core/src/main/resources/i18n/displayStrings_ru.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Запереть средства: dao.bonding.dashboard.unlockingAmount=Разблокировка средств (дождитесь окончания времени блокировки): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Обеспеченная роль +dao.bond.lockupReason.BONDED_ROLE=Обеспеченная роль # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Обеспеченная репутация +dao.bond.lockupReason.REPUTATION=Обеспеченная репутация # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Арбитр # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_sr.properties b/core/src/main/resources/i18n/displayStrings_sr.properties index 74732beef2..235d12c4a4 100644 --- a/core/src/main/resources/i18n/displayStrings_sr.properties +++ b/core/src/main/resources/i18n/displayStrings_sr.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds: dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_th.properties b/core/src/main/resources/i18n/displayStrings_th.properties index e837096100..c4be425891 100644 --- a/core/src/main/resources/i18n/displayStrings_th.properties +++ b/core/src/main/resources/i18n/displayStrings_th.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds: dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_vi.properties b/core/src/main/resources/i18n/displayStrings_vi.properties index b70aa05088..207dcc5cef 100644 --- a/core/src/main/resources/i18n/displayStrings_vi.properties +++ b/core/src/main/resources/i18n/displayStrings_vi.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds: dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator # suppress inspection "UnusedProperty" diff --git a/core/src/main/resources/i18n/displayStrings_zh.properties b/core/src/main/resources/i18n/displayStrings_zh.properties index a7d1865639..a85664b837 100644 --- a/core/src/main/resources/i18n/displayStrings_zh.properties +++ b/core/src/main/resources/i18n/displayStrings_zh.properties @@ -1143,9 +1143,9 @@ dao.bonding.dashboard.lockupAmount=Lockup funds: dao.bonding.dashboard.unlockingAmount=Unlocking funds (wait until lock time is over): # suppress inspection "UnusedProperty" -dao.bond.lockupType.BONDED_ROLE=Bonded role +dao.bond.lockupReason.BONDED_ROLE=Bonded role # suppress inspection "UnusedProperty" -dao.bond.lockupType.REPUTATION=Bonded reputation +dao.bond.lockupReason.REPUTATION=Bonded reputation # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator # suppress inspection "UnusedProperty" diff --git a/desktop/src/main/java/bisq/desktop/main/dao/bonding/BondingViewUtils.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/BondingViewUtils.java index 9aa2bdc6c7..5f1e927ffa 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/BondingViewUtils.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/BondingViewUtils.java @@ -26,10 +26,10 @@ import bisq.desktop.util.GUIUtil; import bisq.core.btc.setup.WalletsSetup; import bisq.core.dao.DaoFacade; -import bisq.core.dao.governance.bond.lockup.LockupType; +import bisq.core.dao.governance.bond.lockup.LockupReason; import bisq.core.dao.governance.bond.reputation.MyReputation; import bisq.core.dao.governance.bond.reputation.MyReputationListService; -import bisq.core.dao.governance.bond.role.BondedRolesService; +import bisq.core.dao.governance.bond.role.BondedRolesRepository; import bisq.core.dao.state.model.blockchain.TxOutput; import bisq.core.dao.state.model.governance.BondedRoleType; import bisq.core.dao.state.model.governance.Role; @@ -56,7 +56,7 @@ import static com.google.common.base.Preconditions.checkArgument; public class BondingViewUtils { private final P2PService p2PService; private final MyReputationListService myReputationListService; - private final BondedRolesService bondedRolesService; + private final BondedRolesRepository bondedRolesRepository; private final WalletsSetup walletsSetup; private final DaoFacade daoFacade; private final Navigation navigation; @@ -65,14 +65,14 @@ public class BondingViewUtils { @Inject public BondingViewUtils(P2PService p2PService, MyReputationListService myReputationListService, - BondedRolesService bondedRolesService, + BondedRolesRepository bondedRolesRepository, WalletsSetup walletsSetup, DaoFacade daoFacade, Navigation navigation, BsqFormatter bsqFormatter) { this.p2PService = p2PService; this.myReputationListService = myReputationListService; - this.bondedRolesService = bondedRolesService; + this.bondedRolesRepository = bondedRolesRepository; this.walletsSetup = walletsSetup; this.daoFacade = daoFacade; this.navigation = navigation; @@ -83,8 +83,8 @@ public class BondingViewUtils { BondedRoleType bondedRoleType = role.getBondedRoleType(); Coin lockupAmount = Coin.valueOf(bondedRoleType.getRequiredBond()); int lockupTime = bondedRoleType.getUnlockTimeInBlocks(); - if (!bondedRolesService.wasBondedAssetAlreadyBonded(role)) { - lockupBond(role.getHash(), lockupAmount, lockupTime, LockupType.BONDED_ROLE, resultHandler); + if (!bondedRolesRepository.isBondedAssetAlreadyInBond(role)) { + lockupBond(role.getHash(), lockupAmount, lockupTime, LockupReason.BONDED_ROLE, resultHandler); } else { handleError(new RuntimeException("The role has been used already for a lockup tx.")); } @@ -92,11 +92,11 @@ public class BondingViewUtils { public void lockupBondForReputation(Coin lockupAmount, int lockupTime, byte[] salt, Consumer resultHandler) { MyReputation myReputation = new MyReputation(salt); - lockupBond(myReputation.getHash(), lockupAmount, lockupTime, LockupType.REPUTATION, resultHandler); + lockupBond(myReputation.getHash(), lockupAmount, lockupTime, LockupReason.REPUTATION, resultHandler); myReputationListService.addReputation(myReputation); } - private void lockupBond(byte[] hash, Coin lockupAmount, int lockupTime, LockupType lockupType, + private void lockupBond(byte[] hash, Coin lockupAmount, int lockupTime, LockupReason lockupReason, Consumer resultHandler) { if (GUIUtil.isReadyForTxBroadcast(p2PService, walletsSetup)) { if (!DevEnv.isDevMode()) { @@ -106,21 +106,21 @@ public class BondingViewUtils { lockupTime )) .actionButtonText(Res.get("shared.yes")) - .onAction(() -> publishLockupTx(hash, lockupAmount, lockupTime, lockupType, resultHandler)) + .onAction(() -> publishLockupTx(hash, lockupAmount, lockupTime, lockupReason, resultHandler)) .closeButtonText(Res.get("shared.cancel")) .show(); } else { - publishLockupTx(hash, lockupAmount, lockupTime, lockupType, resultHandler); + publishLockupTx(hash, lockupAmount, lockupTime, lockupReason, resultHandler); } } else { GUIUtil.showNotReadyForTxBroadcastPopups(p2PService, walletsSetup); } } - private void publishLockupTx(byte[] hash, Coin lockupAmount, int lockupTime, LockupType lockupType, Consumer resultHandler) { + private void publishLockupTx(byte[] hash, Coin lockupAmount, int lockupTime, LockupReason lockupReason, Consumer resultHandler) { daoFacade.publishLockupTx(lockupAmount, lockupTime, - lockupType, + lockupReason, hash, txId -> { if (!DevEnv.isDevMode()) diff --git a/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java index 9911b15556..99d9e1e5c6 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java @@ -22,7 +22,7 @@ import bisq.desktop.main.dao.bonding.BondingViewUtils; import bisq.core.dao.DaoFacade; import bisq.core.dao.governance.bond.Bond; import bisq.core.dao.governance.bond.role.BondedRole; -import bisq.core.dao.governance.bond.role.BondedRolesService; +import bisq.core.dao.governance.bond.role.BondedRolesRepository; import bisq.core.dao.state.DaoStateListener; import bisq.core.dao.state.model.blockchain.Block; import bisq.core.locale.Res; @@ -48,7 +48,7 @@ import lombok.extern.slf4j.Slf4j; class BondListItem implements DaoStateListener { private final Bond bond; private final DaoFacade daoFacade; - private final BondedRolesService bondedRolesService; + private final BondedRolesRepository bondedRolesRepository; private final BondingViewUtils bondingViewUtils; private final BsqFormatter bsqFormatter; private final String bondType; @@ -64,12 +64,12 @@ class BondListItem implements DaoStateListener { BondListItem(Bond bond, DaoFacade daoFacade, - BondedRolesService bondedRolesService, + BondedRolesRepository bondedRolesRepository, BondingViewUtils bondingViewUtils, BsqFormatter bsqFormatter) { this.bond = bond; this.daoFacade = daoFacade; - this.bondedRolesService = bondedRolesService; + this.bondedRolesRepository = bondedRolesRepository; this.bondingViewUtils = bondingViewUtils; this.bsqFormatter = bsqFormatter; diff --git a/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondsView.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondsView.java index 4d44297a66..c009517525 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondsView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondsView.java @@ -28,7 +28,7 @@ import bisq.desktop.util.validation.BsqValidator; import bisq.core.btc.listeners.BsqBalanceListener; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.dao.DaoFacade; -import bisq.core.dao.governance.bond.role.BondedRolesService; +import bisq.core.dao.governance.bond.role.BondedRolesRepository; import bisq.core.dao.state.DaoStateListener; import bisq.core.dao.state.model.blockchain.Block; import bisq.core.locale.Res; @@ -75,7 +75,7 @@ public class BondsView extends ActivatableView implements BsqBal private final BsqFormatter bsqFormatter; private final BsqValidator bsqValidator; private final BondingViewUtils bondingViewUtils; - private final BondedRolesService bondedRolesService; + private final BondedRolesRepository bondedRolesRepository; private final DaoFacade daoFacade; private final Preferences preferences; @@ -97,14 +97,14 @@ public class BondsView extends ActivatableView implements BsqBal BsqFormatter bsqFormatter, BsqValidator bsqValidator, BondingViewUtils bondingViewUtils, - BondedRolesService bondedRolesService, + BondedRolesRepository bondedRolesRepository, DaoFacade daoFacade, Preferences preferences) { this.bsqWalletService = bsqWalletService; this.bsqFormatter = bsqFormatter; this.bsqValidator = bsqValidator; this.bondingViewUtils = bondingViewUtils; - this.bondedRolesService = bondedRolesService; + this.bondedRolesRepository = bondedRolesRepository; this.daoFacade = daoFacade; this.preferences = preferences; } @@ -208,7 +208,7 @@ public class BondsView extends ActivatableView implements BsqBal .map(bond -> { return new BondListItem(bond, daoFacade, - bondedRolesService, + bondedRolesRepository, bondingViewUtils, bsqFormatter); })