mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-20 13:54:32 +01:00
Merge pull request #5764 from chimp1984/avoid-usage-of-outdated-addresses
Avoid that outdated donation and fee addresses are used.
This commit is contained in:
commit
06da45fb7a
9 changed files with 103 additions and 35 deletions
|
@ -73,6 +73,7 @@ import bisq.core.dao.state.model.governance.Role;
|
|||
import bisq.core.dao.state.model.governance.RoleProposal;
|
||||
import bisq.core.dao.state.model.governance.Vote;
|
||||
import bisq.core.dao.state.storage.DaoStateStorageService;
|
||||
import bisq.core.trade.DelayedPayoutAddressProvider;
|
||||
|
||||
import bisq.asset.Asset;
|
||||
|
||||
|
@ -799,9 +800,9 @@ public class DaoFacade implements DaoSetupService {
|
|||
if (Config.baseCurrencyNetwork().isMainnet()) {
|
||||
// If Dao is deactivated we need to add the past addresses used as well.
|
||||
// This list need to be updated once a new address gets defined.
|
||||
allPastParamValues.add("3EtUWqsGThPtjwUczw27YCo6EWvQdaPUyp"); // burning man 2019
|
||||
allPastParamValues.add("3A8Zc1XioE2HRzYfbb5P8iemCS72M6vRJV"); // burningman2
|
||||
allPastParamValues.add("34VLFgtFKAtwTdZ5rengTT2g2zC99sWQLC"); // burningman3 (https://github.com/bisq-network/roles/issues/80#issuecomment-723577776)
|
||||
allPastParamValues.add(DelayedPayoutAddressProvider.BM2019_ADDRESS);
|
||||
allPastParamValues.add(DelayedPayoutAddressProvider.BM2_ADDRESS);
|
||||
allPastParamValues.add(DelayedPayoutAddressProvider.BM3_ADDRESS);
|
||||
}
|
||||
|
||||
return allPastParamValues;
|
||||
|
|
|
@ -18,11 +18,13 @@
|
|||
package bisq.core.dao.state;
|
||||
|
||||
import bisq.core.dao.DaoSetupService;
|
||||
import bisq.core.dao.governance.param.Param;
|
||||
import bisq.core.dao.monitoring.DaoStateMonitoringService;
|
||||
import bisq.core.dao.monitoring.model.DaoStateHash;
|
||||
import bisq.core.dao.state.model.DaoState;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.dao.state.storage.DaoStateStorageService;
|
||||
import bisq.core.trade.DelayedPayoutAddressProvider;
|
||||
import bisq.core.user.Preferences;
|
||||
|
||||
import bisq.common.config.Config;
|
||||
|
@ -62,6 +64,7 @@ public class DaoStateSnapshotService implements DaoSetupService, DaoStateListene
|
|||
private final DaoStateStorageService daoStateStorageService;
|
||||
private final DaoStateMonitoringService daoStateMonitoringService;
|
||||
private final Preferences preferences;
|
||||
private final Config config;
|
||||
private final File storageDir;
|
||||
|
||||
private protobuf.DaoState daoStateCandidate;
|
||||
|
@ -86,12 +89,14 @@ public class DaoStateSnapshotService implements DaoSetupService, DaoStateListene
|
|||
DaoStateStorageService daoStateStorageService,
|
||||
DaoStateMonitoringService daoStateMonitoringService,
|
||||
Preferences preferences,
|
||||
Config config,
|
||||
@Named(Config.STORAGE_DIR) File storageDir) {
|
||||
this.daoStateService = daoStateService;
|
||||
this.genesisTxInfo = genesisTxInfo;
|
||||
this.daoStateStorageService = daoStateStorageService;
|
||||
this.daoStateMonitoringService = daoStateMonitoringService;
|
||||
this.preferences = preferences;
|
||||
this.config = config;
|
||||
this.storageDir = storageDir;
|
||||
}
|
||||
|
||||
|
@ -114,6 +119,20 @@ public class DaoStateSnapshotService implements DaoSetupService, DaoStateListene
|
|||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onParseBlockCompleteAfterBatchProcessing(Block block) {
|
||||
if (config.baseCurrencyNetwork.isMainnet()) {
|
||||
// In case the DAO state is invalid we might get an outdated RECIPIENT_BTC_ADDRESS. In that case we trigger
|
||||
// a dao resync from resources.
|
||||
String address = daoStateService.getParamValue(Param.RECIPIENT_BTC_ADDRESS, daoStateService.getChainHeight());
|
||||
if (DelayedPayoutAddressProvider.isOutdatedAddress(address)) {
|
||||
log.warn("The RECIPIENT_BTC_ADDRESS is not as expected. The DAO state is probably out of " +
|
||||
"sync and a resync should fix that issue.");
|
||||
resyncDaoStateFromResources();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We listen onDaoStateChanged to ensure the dao state has been processed from listener clients after parsing.
|
||||
// We need to listen during batch processing as well to write snapshots during that process.
|
||||
@Override
|
||||
|
|
|
@ -66,7 +66,7 @@ public class CreateMakerFeeTx extends Task<PlaceOfferModel> {
|
|||
|
||||
TradeWalletService tradeWalletService = model.getTradeWalletService();
|
||||
|
||||
String feeReceiver = FeeReceiverSelector.getAddress(model.getDaoFacade(), model.getFilterManager());
|
||||
String feeReceiver = FeeReceiverSelector.getAddress(model.getFilterManager());
|
||||
|
||||
if (offer.isCurrencyForMakerFeeBtc()) {
|
||||
tradeWalletService.createBtcTradingFeeTx(
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.trade;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.param.Param;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class DelayedPayoutAddressProvider {
|
||||
public static final String INITIAL_BM_ADDRESS = "1BVxNn3T12veSK6DgqwU4Hdn7QHcDDRag7"; // Initial DAO donation address
|
||||
public static final String BM2019_ADDRESS = "3EtUWqsGThPtjwUczw27YCo6EWvQdaPUyp"; // burning2019
|
||||
public static final String BM2_ADDRESS = "3A8Zc1XioE2HRzYfbb5P8iemCS72M6vRJV"; // burningman2
|
||||
// burningman3 https://github.com/bisq-network/roles/issues/80#issuecomment-723577776
|
||||
public static final String BM3_ADDRESS = "34VLFgtFKAtwTdZ5rengTT2g2zC99sWQLC";
|
||||
|
||||
public static String getDelayedPayoutAddress(DaoFacade daoFacade) {
|
||||
String address = daoFacade.getParamValue(Param.RECIPIENT_BTC_ADDRESS);
|
||||
if (isOutdatedAddress(address)) {
|
||||
log.warn("Outdated delayed payout address. " +
|
||||
"This can be the case if the DAO is deactivated or if the user has an invalid DAO state." +
|
||||
"We set the address to the recent one (BM3_ADDRESS).");
|
||||
return getAddress();
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
public static boolean isOutdatedAddress(String address) {
|
||||
return address.equals(INITIAL_BM_ADDRESS) ||
|
||||
address.equals(BM2019_ADDRESS) ||
|
||||
address.equals(BM2_ADDRESS);
|
||||
}
|
||||
|
||||
public static String getAddress() {
|
||||
return BM3_ADDRESS;
|
||||
}
|
||||
}
|
|
@ -65,7 +65,7 @@ public class CreateTakerFeeTx extends TradeTask {
|
|||
TradeWalletService tradeWalletService = processModel.getTradeWalletService();
|
||||
Transaction transaction;
|
||||
|
||||
String feeReceiver = FeeReceiverSelector.getAddress(processModel.getDaoFacade(), processModel.getFilterManager());
|
||||
String feeReceiver = FeeReceiverSelector.getAddress(processModel.getFilterManager());
|
||||
|
||||
if (trade.isCurrencyForTakerFeeBtc()) {
|
||||
transaction = tradeWalletService.createBtcTradingFeeTx(
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
package bisq.core.util;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.param.Param;
|
||||
import bisq.core.filter.FilterManager;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
@ -34,12 +32,18 @@ import lombok.extern.slf4j.Slf4j;
|
|||
|
||||
@Slf4j
|
||||
public class FeeReceiverSelector {
|
||||
public static String getAddress(DaoFacade daoFacade, FilterManager filterManager) {
|
||||
return getAddress(daoFacade, filterManager, new Random());
|
||||
public static final String BTC_FEE_RECEIVER_ADDRESS = "38bZBj5peYS3Husdz7AH3gEUiUbYRD951t";
|
||||
|
||||
public static String getMostRecentAddress() {
|
||||
return BTC_FEE_RECEIVER_ADDRESS;
|
||||
}
|
||||
|
||||
public static String getAddress(FilterManager filterManager) {
|
||||
return getAddress(filterManager, new Random());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static String getAddress(DaoFacade daoFacade, FilterManager filterManager, Random rnd) {
|
||||
static String getAddress(FilterManager filterManager, Random rnd) {
|
||||
List<String> feeReceivers = Optional.ofNullable(filterManager.getFilter())
|
||||
.flatMap(f -> Optional.ofNullable(f.getBtcFeeReceiverAddresses()))
|
||||
.orElse(List.of());
|
||||
|
@ -61,8 +65,8 @@ public class FeeReceiverSelector {
|
|||
return receiverAddressList.get(weightedSelection(amountList, rnd));
|
||||
}
|
||||
|
||||
// We keep default value as fallback in case no filter value is available or user has old version.
|
||||
return daoFacade.getParamValue(Param.RECIPIENT_BTC_ADDRESS);
|
||||
// If no fee address receiver is defined via filter we use the hard coded recent address
|
||||
return getMostRecentAddress();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
|
|
@ -39,6 +39,7 @@ public class DaoStateSnapshotServiceTest {
|
|||
mock(DaoStateStorageService.class),
|
||||
mock(DaoStateMonitoringService.class),
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,15 +19,17 @@ package bisq.core.provider.mempool;
|
|||
|
||||
import bisq.core.dao.governance.param.Param;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.trade.DelayedPayoutAddressProvider;
|
||||
import bisq.core.util.FeeReceiverSelector;
|
||||
import bisq.core.util.ParsingUtils;
|
||||
import bisq.core.util.coin.BsqFormatter;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -43,8 +45,8 @@ import org.slf4j.LoggerFactory;
|
|||
import org.mockito.Mockito;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
@ -61,11 +63,11 @@ public class TxValidatorTest {
|
|||
btcFeeReceivers.add("13sxMq8mTw7CTSqgGiMPfwo6ZDsVYrHLmR");
|
||||
btcFeeReceivers.add("19qA2BVPoyXDfHKVMovKG7SoxGY7xrBV8c");
|
||||
btcFeeReceivers.add("19BNi5EpZhgBBWAt5ka7xWpJpX2ZWJEYyq");
|
||||
btcFeeReceivers.add("38bZBj5peYS3Husdz7AH3gEUiUbYRD951t");
|
||||
btcFeeReceivers.add("3EtUWqsGThPtjwUczw27YCo6EWvQdaPUyp");
|
||||
btcFeeReceivers.add(FeeReceiverSelector.BTC_FEE_RECEIVER_ADDRESS);
|
||||
btcFeeReceivers.add(DelayedPayoutAddressProvider.BM2019_ADDRESS);
|
||||
btcFeeReceivers.add("1BVxNn3T12veSK6DgqwU4Hdn7QHcDDRag7");
|
||||
btcFeeReceivers.add("3A8Zc1XioE2HRzYfbb5P8iemCS72M6vRJV");
|
||||
btcFeeReceivers.add("34VLFgtFKAtwTdZ5rengTT2g2zC99sWQLC");
|
||||
btcFeeReceivers.add(DelayedPayoutAddressProvider.BM3_ADDRESS);
|
||||
log.warn("Known BTC fee receivers: {}", btcFeeReceivers.toString());
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
package bisq.core.util;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.param.Param;
|
||||
import bisq.core.filter.Filter;
|
||||
import bisq.core.filter.FilterManager;
|
||||
|
||||
|
@ -42,8 +40,6 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FeeReceiverSelectorTest {
|
||||
@Mock
|
||||
private DaoFacade daoFacade;
|
||||
@Mock
|
||||
private FilterManager filterManager;
|
||||
|
||||
|
@ -55,7 +51,7 @@ public class FeeReceiverSelectorTest {
|
|||
|
||||
Map<String, Integer> selectionCounts = new HashMap<>();
|
||||
for (int i = 0; i < 400; i++) {
|
||||
String address = FeeReceiverSelector.getAddress(daoFacade, filterManager, rnd);
|
||||
String address = FeeReceiverSelector.getAddress(filterManager, rnd);
|
||||
selectionCounts.compute(address, (k, n) -> n != null ? n + 1 : 1);
|
||||
}
|
||||
|
||||
|
@ -69,34 +65,26 @@ public class FeeReceiverSelectorTest {
|
|||
|
||||
@Test
|
||||
public void testGetAddress_noValidReceivers_nullFilter() {
|
||||
when(daoFacade.getParamValue(Param.RECIPIENT_BTC_ADDRESS)).thenReturn("default");
|
||||
|
||||
when(filterManager.getFilter()).thenReturn(null);
|
||||
assertEquals("default", FeeReceiverSelector.getAddress(daoFacade, filterManager));
|
||||
assertEquals(FeeReceiverSelector.getMostRecentAddress(), FeeReceiverSelector.getAddress(filterManager));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAddress_noValidReceivers_filterWithNullList() {
|
||||
when(daoFacade.getParamValue(Param.RECIPIENT_BTC_ADDRESS)).thenReturn("default");
|
||||
|
||||
when(filterManager.getFilter()).thenReturn(filterWithReceivers(null));
|
||||
assertEquals("default", FeeReceiverSelector.getAddress(daoFacade, filterManager));
|
||||
assertEquals(FeeReceiverSelector.getMostRecentAddress(), FeeReceiverSelector.getAddress(filterManager));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAddress_noValidReceivers_filterWithEmptyList() {
|
||||
when(daoFacade.getParamValue(Param.RECIPIENT_BTC_ADDRESS)).thenReturn("default");
|
||||
|
||||
when(filterManager.getFilter()).thenReturn(filterWithReceivers(List.of()));
|
||||
assertEquals("default", FeeReceiverSelector.getAddress(daoFacade, filterManager));
|
||||
assertEquals(FeeReceiverSelector.getMostRecentAddress(), FeeReceiverSelector.getAddress(filterManager));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAddress_noValidReceivers_filterWithIllFormedList() {
|
||||
when(daoFacade.getParamValue(Param.RECIPIENT_BTC_ADDRESS)).thenReturn("default");
|
||||
|
||||
when(filterManager.getFilter()).thenReturn(filterWithReceivers(List.of("ill-formed")));
|
||||
assertEquals("default", FeeReceiverSelector.getAddress(daoFacade, filterManager));
|
||||
assertEquals(FeeReceiverSelector.getMostRecentAddress(), FeeReceiverSelector.getAddress(filterManager));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Add table
Reference in a new issue