diff --git a/src/main/java/org/qora/DecodeOnlineAccounts.java b/src/main/java/org/qora/DecodeOnlineAccounts.java new file mode 100644 index 00000000..4456274c --- /dev/null +++ b/src/main/java/org/qora/DecodeOnlineAccounts.java @@ -0,0 +1,105 @@ +package org.qora; + +import java.security.Security; + +import org.bitcoinj.core.Base58; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider; +import org.qora.block.BlockChain; +import org.qora.controller.Controller; +import org.qora.data.account.RewardShareData; +import org.qora.gui.Gui; +import org.qora.repository.DataException; +import org.qora.repository.Repository; +import org.qora.repository.RepositoryFactory; +import org.qora.repository.RepositoryManager; +import org.qora.repository.hsqldb.HSQLDBRepositoryFactory; +import org.qora.settings.Settings; +import org.qora.transform.block.BlockTransformer; +import org.roaringbitmap.IntIterator; + +import io.druid.extendedset.intset.ConciseSet; + +public class DecodeOnlineAccounts { + + private static void usage() { + System.err.println("Usage: DecodeOnlineAccounts [] "); + System.err.println("Example: DecodeOnlineAccounts 4GmR5B"); + System.err.println("Example: DecodeOnlineAccounts settings-test.json 4GmR5B"); + System.exit(1); + } + + public static void main(String[] args) { + if (args.length < 1 || args.length > 2) + usage(); + + byte[] encodedOnlineAccounts = Base58.decode(args[args.length - 1]); + + ConciseSet accountIndexes = BlockTransformer.decodeOnlineAccounts(encodedOnlineAccounts); + + String delimiter = ""; + System.out.print("Account indexes: "); + + IntIterator iterator = accountIndexes.iterator(); + while (iterator.hasNext()) { + int accountIndex = iterator.next(); + + System.out.print(String.format("%s%d", delimiter, accountIndex)); + delimiter = ", "; + } + System.out.println(); + + Security.insertProviderAt(new BouncyCastleProvider(), 0); + Security.insertProviderAt(new BouncyCastleJsseProvider(), 1); + + // Load/check settings, which potentially sets up blockchain config, etc. + try { + if (args.length > 1) + Settings.fileInstance(args[0]); + else + Settings.getInstance(); + } catch (Throwable t) { + Gui.getInstance().fatalError("Settings file", t.getMessage()); + return; // Not System.exit() so that GUI can display error + } + + try { + RepositoryFactory repositoryFactory = new HSQLDBRepositoryFactory(Controller.getRepositoryUrl()); + RepositoryManager.setRepositoryFactory(repositoryFactory); + } catch (DataException e) { + System.err.println("Couldn't connect to repository: " + e.getMessage()); + System.exit(2); + } + + try { + BlockChain.validate(); + } catch (DataException e) { + System.err.println("Couldn't validate repository: " + e.getMessage()); + System.exit(2); + } + + try (final Repository repository = RepositoryManager.getRepository()) { + iterator = accountIndexes.iterator(); + while (iterator.hasNext()) { + int accountIndex = iterator.next(); + + RewardShareData rewardShareData = repository.getAccountRepository().getRewardShareByIndex(accountIndex); + + System.out.println(String.format("Reward-share public key: %s, minter: %s, recipient: %s, share: %s", + Base58.encode(rewardShareData.getRewardSharePublicKey()), + rewardShareData.getMintingAccount(), rewardShareData.getRecipient(), + rewardShareData.getSharePercent().toPlainString())); + } + } catch (DataException e) { + e.printStackTrace(); + } + + try { + RepositoryManager.closeRepositoryFactory(); + } catch (DataException e) { + e.printStackTrace(); + } + + } + +} diff --git a/src/main/java/org/qora/block/Block.java b/src/main/java/org/qora/block/Block.java index 6267b117..81f8703e 100644 --- a/src/main/java/org/qora/block/Block.java +++ b/src/main/java/org/qora/block/Block.java @@ -133,15 +133,12 @@ public class Block { final Account mintingAccount; final AccountData mintingAccountData; final boolean isMinterFounder; - final int shareBin; final Account recipientAccount; final AccountData recipientAccountData; final boolean isRecipientFounder; ExpandedAccount(Repository repository, int accountIndex) throws DataException { - final List sharesByLevel = BlockChain.getInstance().getBlockSharesByLevel(); - this.rewardShareData = repository.getAccountRepository().getRewardShareByIndex(accountIndex); this.mintingAccount = new PublicKeyAccount(repository, this.rewardShareData.getMinterPublicKey()); @@ -150,23 +147,25 @@ public class Block { this.mintingAccountData = repository.getAccountRepository().getAccount(this.mintingAccount.getAddress()); this.isMinterFounder = Account.isFounder(mintingAccountData.getFlags()); - int currentShareBin = -1; - - if (!this.isMinterFounder) - for (int s = 0; s < sharesByLevel.size(); ++s) - if (sharesByLevel.get(s).levels.contains(this.mintingAccountData.getLevel())) { - currentShareBin = s; - break; - } - - this.shareBin = currentShareBin; - this.recipientAccountData = repository.getAccountRepository().getAccount(this.recipientAccount.getAddress()); this.isRecipientFounder = Account.isFounder(recipientAccountData.getFlags()); this.isRecipientAlsoMinter = this.mintingAccountData.getAddress().equals(this.recipientAccountData.getAddress()); } + int getShareBin() { + if (this.isMinterFounder) + return -1; + + final List sharesByLevel = BlockChain.getInstance().getBlockSharesByLevel(); + + for (int s = 0; s < sharesByLevel.size(); ++s) + if (sharesByLevel.get(s).levels.contains(this.mintingAccountData.getLevel())) + return s; + + return -1; + } + void distribute(BigDecimal accountAmount) throws DataException { final BigDecimal oneHundred = BigDecimal.valueOf(100L); @@ -1601,7 +1600,7 @@ public class Block { LOGGER.trace(() -> String.format("Bin %d share of %s: %s", binIndex, totalAmount.toPlainString(), binAmount.toPlainString())); // Spread across all accounts in bin - List binnedAccounts = expandedAccounts.stream().filter(accountInfo -> !accountInfo.isMinterFounder && accountInfo.shareBin == binIndex).collect(Collectors.toList()); + List binnedAccounts = expandedAccounts.stream().filter(accountInfo -> !accountInfo.isMinterFounder && accountInfo.getShareBin() == binIndex).collect(Collectors.toList()); if (binnedAccounts.isEmpty()) continue; @@ -1717,9 +1716,11 @@ public class Block { // Spread remainder across founder accounts BigDecimal foundersAmount = totalAmount.subtract(sharedAmount); BigDecimal finalSharedAmount = sharedAmount; - LOGGER.debug(() -> String.format("Shared %s of %s, remaining %s to founders", finalSharedAmount.toPlainString(), totalAmount.toPlainString(), foundersAmount.toPlainString())); List founderAccounts = expandedAccounts.stream().filter(accountInfo -> accountInfo.isMinterFounder).collect(Collectors.toList()); + LOGGER.debug(() -> String.format("Shared %s of %s, remaining %s to %d founder%s", + finalSharedAmount.toPlainString(), totalAmount.toPlainString(), + foundersAmount.toPlainString(), founderAccounts.size(), (founderAccounts.size() != 1 ? "s" : ""))); if (founderAccounts.isEmpty()) return;