diff --git a/src/main/java/org/qora/block/BlockChain.java b/src/main/java/org/qora/block/BlockChain.java index fde5ff5e..3cdac273 100644 --- a/src/main/java/org/qora/block/BlockChain.java +++ b/src/main/java/org/qora/block/BlockChain.java @@ -7,7 +7,6 @@ import java.math.BigDecimal; import java.math.MathContext; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -482,25 +481,20 @@ public class BlockChain { rebuildBlockchain(); try (final Repository repository = RepositoryManager.getRepository()) { - Block parentBlock = GenesisBlock.getInstance(repository); - BlockData parentBlockData = parentBlock.getBlockData(); + BlockData detachedBlockData = repository.getBlockRepository().getDetachedBlockSignature(); - while (true) { - // No need to maintain transaction state while ploughing through the entire chain - repository.discardChanges(); + if (detachedBlockData != null) { + LOGGER.error(String.format("Block %d's reference does not match any block's signature", detachedBlockData.getHeight())); - BlockData childBlockData = parentBlock.getChild(); - if (childBlockData == null) - break; - - if (!Arrays.equals(childBlockData.getReference(), parentBlock.getSignature())) { - LOGGER.error(String.format("Block %d's reference does not match block %d's signature", childBlockData.getHeight(), parentBlockData.getHeight())); - rebuildBlockchain(); - return; + // Wait for blockchain lock (whereas orphan() only tries to get lock) + ReentrantLock blockchainLock = Controller.getInstance().getBlockchainLock(); + blockchainLock.lock(); + try { + LOGGER.info(String.format("Orphaning back to block %d", detachedBlockData.getHeight() - 1)); + orphan(detachedBlockData.getHeight() - 1); + } finally { + blockchainLock.unlock(); } - - parentBlock = new Block(repository, childBlockData); - parentBlockData = childBlockData; } } } @@ -523,9 +517,9 @@ public class BlockChain { private static void rebuildBlockchain() throws DataException { // (Re)build repository - try (final Repository repository = RepositoryManager.getRepository()) { - repository.rebuild(); + RepositoryManager.rebuild(); + try (final Repository repository = RepositoryManager.getRepository()) { GenesisBlock genesisBlock = GenesisBlock.getInstance(repository); // Add Genesis Block to blockchain @@ -533,7 +527,7 @@ public class BlockChain { repository.saveChanges(); - // Give Network a change to install initial seed peers + // Give Network a chance to install initial seed peers Network.installInitialPeers(repository); } } diff --git a/src/main/java/org/qora/block/GenesisBlock.java b/src/main/java/org/qora/block/GenesisBlock.java index 8912121a..5f4cd148 100644 --- a/src/main/java/org/qora/block/GenesisBlock.java +++ b/src/main/java/org/qora/block/GenesisBlock.java @@ -32,6 +32,7 @@ import org.qora.transform.TransformationException; import org.qora.transform.transaction.TransactionTransformer; import com.google.common.primitives.Bytes; +import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; public class GenesisBlock extends Block { @@ -126,9 +127,9 @@ public class GenesisBlock extends Block { int transactionCount = transactionsData.size(); BigDecimal totalFees = BigDecimal.ZERO.setScale(8); byte[] minterPublicKey = GenesisAccount.PUBLIC_KEY; - byte[] bytesForSignature = getBytesForSignature(info.version, reference, minterPublicKey); - byte[] minterSignature = calcSignature(bytesForSignature); - byte[] transactionsSignature = minterSignature; + byte[] bytesForSignature = getBytesForMinterSignature(info.timestamp, reference, minterPublicKey); + byte[] minterSignature = calcGenesisMinterSignature(bytesForSignature); + byte[] transactionsSignature = calcGenesisTransactionsSignature(); int height = 1; int atCount = 0; BigDecimal atFees = BigDecimal.ZERO.setScale(8); @@ -197,31 +198,29 @@ public class GenesisBlock extends Block { } /** - * Generate genesis block minter/transactions signature. + * Generate genesis block minter signature. *

* This is handled differently as there is no private key for the genesis account and so no way to sign data. - *

- * Instead we return the SHA-256 digest of the block, duplicated so that the returned byte[] is the same length as normal block signatures. * * @return byte[] */ - private static byte[] calcSignature(byte[] bytes) { - byte[] digest = Crypto.digest(bytes); - return Bytes.concat(digest, digest); + private static byte[] calcGenesisMinterSignature(byte[] bytes) { + return Crypto.dupDigest(bytes); } - private static byte[] getBytesForSignature(int version, byte[] reference, byte[] minterPublicKey) { + private static byte[] getBytesForMinterSignature(long timestamp, byte[] reference, byte[] minterPublicKey) { try { // Passing expected size to ByteArrayOutputStream avoids reallocation when adding more bytes than default 32. // See below for explanation of some of the values used to calculated expected size. ByteArrayOutputStream bytes = new ByteArrayOutputStream(8 + 64 + 8 + 32); /* - * NOTE: Historic code had genesis block using Longs.toByteArray() compared to standard block's Ints.toByteArray. The subsequent + * NOTE: Historic code had genesis block using Longs.toByteArray(version) compared to standard block's Ints.toByteArray. The subsequent * Bytes.ensureCapacity(versionBytes, 0, 4) did not truncate versionBytes back to 4 bytes either. This means 8 bytes were used even though * VERSION_LENGTH is set to 4. Correcting this historic bug will break genesis block signatures! */ - bytes.write(Longs.toByteArray(version)); + // For Qortal, we use genesis timestamp instead + bytes.write(Longs.toByteArray(timestamp)); /* * NOTE: Historic code had the reference expanded to only 64 bytes whereas standard block references are 128 bytes. Correcting this historic bug @@ -238,22 +237,41 @@ public class GenesisBlock extends Block { } } + private static byte[] calcGenesisTransactionsSignature() { + // transaction index (int), transaction type (int), creator pubkey (32): so 40 bytes each + ByteArrayOutputStream bytes = new ByteArrayOutputStream(transactionsData.size() * (4 + 4 + 32)); + + try { + for (int ti = 0; ti < transactionsData.size(); ++ti) { + bytes.write(Ints.toByteArray(ti)); + + bytes.write(Ints.toByteArray(transactionsData.get(ti).getType().value)); + + bytes.write(transactionsData.get(ti).getCreatorPublicKey()); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + return Crypto.dupDigest(bytes.toByteArray()); + } + /** Convenience method for calculating genesis block signatures from block data */ private static byte[] calcSignature(BlockData blockData) { - byte[] bytes = getBytesForSignature(blockData.getVersion(), blockData.getReference(), blockData.getMinterPublicKey()); - return calcSignature(bytes); + byte[] bytes = getBytesForMinterSignature(blockData.getTimestamp(), blockData.getReference(), blockData.getMinterPublicKey()); + return Bytes.concat(calcGenesisMinterSignature(bytes), calcGenesisTransactionsSignature()); } @Override public boolean isSignatureValid() { byte[] signature = calcSignature(this.blockData); - // Validate block signature - if (!Arrays.equals(signature, this.blockData.getMinterSignature())) + // Validate block minter's signature (first 64 bytes of block signature) + if (!Arrays.equals(signature, 0, 64, this.blockData.getMinterSignature(), 0, 64)) return false; - // Validate transactions signature - if (!Arrays.equals(signature, this.blockData.getTransactionsSignature())) + // Validate transactions signature (last 64 bytes of block signature) + if (!Arrays.equals(signature, 64, 128, this.blockData.getTransactionsSignature(), 0, 64)) return false; return true; diff --git a/src/main/java/org/qora/crypto/Crypto.java b/src/main/java/org/qora/crypto/Crypto.java index bb44aa0d..07766bd1 100644 --- a/src/main/java/org/qora/crypto/Crypto.java +++ b/src/main/java/org/qora/crypto/Crypto.java @@ -8,6 +8,8 @@ import org.qora.account.Account; import org.qora.block.BlockChain; import org.qora.utils.Base58; +import com.google.common.primitives.Bytes; + public class Crypto { public static final byte ADDRESS_VERSION = 58; @@ -44,6 +46,19 @@ public class Crypto { return digest(digest(input)); } + /** + * Returns 64-byte duplicated digest of message passed in input. + *

+ * Effectively Bytes.concat(digest(input), digest(input)). + * + * @param addressVersion + * @param input + */ + public static byte[] dupDigest(byte[] input) { + final byte[] digest = digest(input); + return Bytes.concat(digest, digest); + } + @SuppressWarnings("deprecation") private static String toAddress(byte addressVersion, byte[] input) { // SHA2-256 input to create new data and of known size diff --git a/src/main/java/org/qora/repository/BlockRepository.java b/src/main/java/org/qora/repository/BlockRepository.java index c289ba0d..f68a7bf8 100644 --- a/src/main/java/org/qora/repository/BlockRepository.java +++ b/src/main/java/org/qora/repository/BlockRepository.java @@ -136,6 +136,13 @@ public interface BlockRepository { */ public int trimOldOnlineAccountsSignatures(long timestamp) throws DataException; + /** + * Returns first (lowest height) block that doesn't link back to genesis block. + * + * @throws DataException + */ + public BlockData getDetachedBlockSignature() throws DataException; + /** * Saves block into repository. * diff --git a/src/main/java/org/qora/repository/RepositoryFactory.java b/src/main/java/org/qora/repository/RepositoryFactory.java index 1bf374e0..cd07d670 100644 --- a/src/main/java/org/qora/repository/RepositoryFactory.java +++ b/src/main/java/org/qora/repository/RepositoryFactory.java @@ -2,6 +2,8 @@ package org.qora.repository; public interface RepositoryFactory { + public RepositoryFactory reopen() throws DataException; + public Repository getRepository() throws DataException; public Repository tryRepository() throws DataException; diff --git a/src/main/java/org/qora/repository/RepositoryManager.java b/src/main/java/org/qora/repository/RepositoryManager.java index de4f4d43..26e8d551 100644 --- a/src/main/java/org/qora/repository/RepositoryManager.java +++ b/src/main/java/org/qora/repository/RepositoryManager.java @@ -35,4 +35,16 @@ public abstract class RepositoryManager { } } + public static void rebuild() throws DataException { + RepositoryFactory oldRepositoryFactory = repositoryFactory; + + // Grab handle repository reference before we close + Repository oldRepository = oldRepositoryFactory.getRepository(); + + // Use old repository reference to perform rebuild + oldRepository.rebuild(); + + repositoryFactory = oldRepositoryFactory.reopen(); + } + } diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java index f85cc94d..6a6e4872 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java @@ -339,6 +339,21 @@ public class HSQLDBBlockRepository implements BlockRepository { } } + @Override + public BlockData getDetachedBlockSignature() throws DataException { + String sql = "SELECT " + BLOCK_DB_COLUMNS + " FROM Blocks " + + "LEFT OUTER JOIN Blocks AS ParentBlocks " + + "ON ParentBlocks.signature = Blocks.reference " + + "WHERE ParentBlocks.signature IS NULL AND Blocks.height > 1 " + + "ORDER BY Blocks.height ASC LIMIT 1"; + + try (ResultSet resultSet = this.repository.checkedExecute(sql)) { + return getBlockFromResultSet(resultSet); + } catch (SQLException e) { + throw new DataException("Error fetching block by signature from repository", e); + } + } + @Override public void save(BlockData blockData) throws DataException { HSQLDBSaver saveHelper = new HSQLDBSaver("Blocks"); diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java index 1c63a2c6..cf0584f3 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java @@ -38,6 +38,7 @@ import org.qora.repository.DataException; import org.qora.repository.NameRepository; import org.qora.repository.NetworkRepository; import org.qora.repository.Repository; +import org.qora.repository.RepositoryManager; import org.qora.repository.TransactionRepository; import org.qora.repository.VotingRepository; import org.qora.repository.hsqldb.transaction.HSQLDBTransactionRepository; @@ -223,6 +224,37 @@ public class HSQLDBRepository implements Repository { @Override public void rebuild() throws DataException { + LOGGER.info("Rebuilding repository from scratch"); + + // Clean out any previous backup + try { + String connectionUrl = this.connection.getMetaData().getURL(); + String dbPathname = getDbPathname(connectionUrl); + if (dbPathname == null) + throw new DataException("Unable to locate repository for rebuild?"); + + // Close repository reference so we can close repository factory cleanly + this.close(); + + // Close repository factory to prevent access + RepositoryManager.closeRepositoryFactory(); + + // No need to wipe files for in-memory database + if (!dbPathname.equals("mem")) { + Path oldRepoDirPath = Paths.get(dbPathname).getParent(); + + // Delete old repository files + Files.walk(oldRepoDirPath) + .sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .filter(file -> file.getPath().startsWith(dbPathname)) + .forEach(File::delete); + } + } catch (NoSuchFileException e) { + // Nothing to remove + } catch (SQLException | IOException e) { + throw new DataException("Unable to remove previous repository"); + } } @Override @@ -252,6 +284,12 @@ public class HSQLDBRepository implements Repository { if (dbPathname == null) throw new DataException("Unable to locate repository for backup?"); + // Doesn't really make sense to backup an in-memory database... + if (dbPathname.equals("mem")) { + LOGGER.debug("Ignoring request to backup in-memory repository!"); + return; + } + String backupUrl = buildBackupUrl(dbPathname); String backupPathname = getDbPathname(backupUrl); if (backupPathname == null) @@ -279,15 +317,18 @@ public class HSQLDBRepository implements Repository { } } - /** Returns DB pathname from passed connection URL. */ + /** Returns DB pathname from passed connection URL. If memory DB, returns "mem". */ private static String getDbPathname(String connectionUrl) { - Pattern pattern = Pattern.compile("file:(.*?);"); + Pattern pattern = Pattern.compile("hsqldb:(mem|file):(.*?)(;|$)"); Matcher matcher = pattern.matcher(connectionUrl); if (!matcher.find()) return null; - return matcher.group(1); + if (matcher.group(1).equals("mem")) + return "mem"; + else + return matcher.group(2); } private static String buildBackupUrl(String dbPathname) { diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBRepositoryFactory.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBRepositoryFactory.java index 229c3abe..534f349d 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBRepositoryFactory.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBRepositoryFactory.java @@ -71,6 +71,11 @@ public class HSQLDBRepositoryFactory implements RepositoryFactory { } } + @Override + public RepositoryFactory reopen() throws DataException { + return new HSQLDBRepositoryFactory(this.connectionUrl); + } + @Override public Repository getRepository() throws DataException { try { diff --git a/src/main/resources/blockchain.json b/src/main/resources/blockchain.json index 875f9e93..8386d544 100644 --- a/src/main/resources/blockchain.json +++ b/src/main/resources/blockchain.json @@ -57,7 +57,7 @@ }, "genesisInfo": { "version": 4, - "timestamp": "1575300000000", + "timestamp": "1576150000000", "transactions": [ { "type": "ISSUE_ASSET", "owner": "QUwGVHPPxJNJ2dq95abQNe79EyBN2K26zM", "assetName": "QORT", "description": "QORTAL coin", "quantity": 0, "isDivisible": true, "reference": "28u54WRcMfGujtQMZ9dNKFXVqucY7XfPihXAqPFsnx853NPUwfDJy1sMH5boCkahFgjUNYqc5fkduxdBhQTKgUsC", "data": "{}" }, { "type": "ISSUE_ASSET", "owner": "QUwGVHPPxJNJ2dq95abQNe79EyBN2K26zM", "assetName": "QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, @@ -71,8 +71,8 @@ { "type": "CREATE_GROUP", "creatorPublicKey": "6rNn9b3pYRrG9UKqzMWYZ9qa8F3Zgv2mVWrULGHUusb", "owner": "QcatTpaU1UneBs3fVHo8QN6mUmuceRVzFY", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT60", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 }, - { "type": "ACCOUNT_LEVEL", "target": "QcrnYL6yNwHKuEzYLXQ8LewG3m2B5k9K5f", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "Qe9VPzQp3h4Kg3DHSHBUQ3AM3AiRBfCDfX", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QcrnYL6yNwHKuEzYLXQ8LewG3m2B5k9K5f", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QVLuvt9krmxXwQPAeAhxzhuMF5i8F4aNs8", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QPYfRd1uhnAgqkZNmjNCjgPhkguMnHWuc4", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QM9zVbXXnfrtQ1X7zPQ5zxPYPAWTaVMXqZ", "level": 5 }, @@ -83,104 +83,201 @@ { "type": "ACCOUNT_LEVEL", "target": "QYgVi26jUqMzJo4ahZV9yekQNnYKHBaX8r", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QTTrv8SWR8huV8TFYUEQhfZ1j1JmtL5p8G", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QQa3MTgdnru5B7wSqPcq7qXcZcpbDQ7oyE", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QWe1iPDudLU189BggPykbH1DrAeaFEgX6W", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QUvoLFfkuVuRe1KGMLQS4nUHry6CBTuTYz", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QTEE4ZJXv68ke4841HWjTLAAU8mfccxwbE", "level": 5 }, - { "type": "ACCOUNT_LEVEL", "target": "QQoHo1x4hvZcSFbj2uQAXQhq2ZXBUgPeNj", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QXan6JJ1WuRi7GigvFDjtTzJY1rfYEqEqv", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QQoHo1x4hvZcSFbj2uQAXQhq2ZXBUgPeNj", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QVurebcEbe4USR4xcS3Mbk12mhxsjRX31u", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QfmM8dgfikTB2FYVuJ9owzQXVm8wP7T4QT", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QPUMyJ59kkrp75tDzDPxSyw1GWCrbC2cS2", "level": 5 }, - { "type": "ACCOUNT_LEVEL", "target": "QVurebcEbe4USR4xcS3Mbk12mhxsjRX31u", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "Qc9dZchoYfc1eRJhSLXR9rxSHcqNB47Dex", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QTMTFswUU83XVmk6T4Gez7qUJCccbAad7S", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QQEZEGWt3sAPwEWYD2RQ6tMwnpkayG81dY", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QPcTWoAhYWmwjmWbQAS8muisrQVaLJMbg7", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QWpJxitn53ovwknQfrCaqivvoUNuPrX2sb", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QLpLY9o3X21q7q4L6u5JdDuMskYA838iYE", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QdGbhtkFHUqd9nK9UegxxGXD1eSRYSoKjt", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QP8xG56L8b28h1mguSk9LuzNhxbHgAoL9b", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QfjL32jLsxtumbfx6ufmfCFCBccVCQFkrh", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QgpAW6uqwNR58gNYWRCVXNLm4F5TuckAw4", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "Qc9dZchoYfc1eRJhSLXR9rxSHcqNB47Dex", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QTMTFswUU83XVmk6T4Gez7qUJCccbAad7S", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QQEZEGWt3sAPwEWYD2RQ6tMwnpkayG81dY", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QPcTWoAhYWmwjmWbQAS8muisrQVaLJMbg7", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QWpJxitn53ovwknQfrCaqivvoUNuPrX2sb", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QLpLY9o3X21q7q4L6u5JdDuMskYA838iYE", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QdGbhtkFHUqd9nK9UegxxGXD1eSRYSoKjt", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QP8xG56L8b28h1mguSk9LuzNhxbHgAoL9b", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QfjL32jLsxtumbfx6ufmfCFCBccVCQFkrh", "level": 5 }, + { "type": "ACCOUNT_LEVEL", "target": "QgpAW6uqwNR58gNYWRCVXNLm4F5TuckAw4", "level": 5 }, { "type": "ACCOUNT_LEVEL", "target": "QbwgBD6LWdk1hZsb8EwdVVmDZdvpxMzyGT", "level": 4 }, { "type": "ACCOUNT_LEVEL", "target": "QawB5MesBratjs2d9EMnXnrN4EC7gw7LRw", "level": 4 }, { "type": "ACCOUNT_LEVEL", "target": "QXKmtkHHwaUQzGeHHG2dFiHUnKAp815Mzq", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QdtAQm1EGNgM7QDSaC2qvV9WdpRHwpApUT", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QZkThgFfExognAbxLjYZGVHpL7X6g3EG4A", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QRFHr4jnVgvAsPTubeSrh8bPy1yzwzYaWD", "level": 4 }, { "type": "ACCOUNT_LEVEL", "target": "QdXe21sjY8smjVmiAUgZY8xWVzwgxMgK5A", "level": 4 }, - { "type": "ACCOUNT_LEVEL", "target": "QbH8srDKeS5VcsQsgsaF3nqCzGT1NqfsTx", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QVkQTr8PzDTaNxhvrC47UUxUi6V987a5qL", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QbqRyFw7Xu6Nsb4FraaUSe7nUPukuUpekG", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QUzUCfoakDqBaL5zBgfvTKLHcuxbUfB38Q", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QSBJuNoCAFUTcevuCTcMi3i5nzNPhC5R4b", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QguNJ4evpN9i76dYHysTzLiKoWKFhE4B4U", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QiBYApdEYRwsFYjt59UJqZV55wcwykvhsh", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QhMEWhZCufhKLkfuNU2DAzj1mmWoAxX147", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QNJ8jDx6Mni2GKLHEY1BMh9xDumT3vnJQM", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QWe1iPDudLU189BggPykbH1DrAeaFEgX6W", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QZsygC1chppsJK1cnaHG4fEsNaDYfLF7ZJ", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QaFN7DWcGF7keNACJpwCVnegePbfsAoFCw", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "Qgwb5SLVGAperXAMoVNBDvGpVAxTVY7f6F", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QXv4WiqgryFPi8BgX7RU7gqtAgrVutmU4S", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QjEAs2or122weKppv5zALzoQzXxbsDjy3f", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QZkThgFfExognAbxLjYZGVHpL7X6g3EG4A", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QdtAQm1EGNgM7QDSaC2qvV9WdpRHwpApUT", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QbH8srDKeS5VcsQsgsaF3nqCzGT1NqfsTx", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QRFHr4jnVgvAsPTubeSrh8bPy1yzwzYaWD", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QVkQTr8PzDTaNxhvrC47UUxUi6V987a5qL", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QguNJ4evpN9i76dYHysTzLiKoWKFhE4B4U", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QbqRyFw7Xu6Nsb4FraaUSe7nUPukuUpekG", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QUzUCfoakDqBaL5zBgfvTKLHcuxbUfB38Q", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QSBJuNoCAFUTcevuCTcMi3i5nzNPhC5R4b", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QiBYApdEYRwsFYjt59UJqZV55wcwykvhsh", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QZvHW7amu5DNktsBgaMrR1brHZhhhVwKLW", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QNJ8jDx6Mni2GKLHEY1BMh9xDumT3vnJQM", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QhMEWhZCufhKLkfuNU2DAzj1mmWoAxX147", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "Qj5ncwncQY4KPYgKHD1eYpXHbR717PeLcJ", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QjrC8NXwR8gFkEauvRwCPxqHroPFqAJbhK", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QY1RFZTD2ogRohf3UrdT4g1Qo9D122AZDN", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QcU4VhU9ohDXU4k4AUMapgJRYSzEpizjLN", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QZsygC1chppsJK1cnaHG4fEsNaDYfLF7ZJ", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QaFN7DWcGF7keNACJpwCVnegePbfsAoFCw", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QYGNMWBmqWgVtMWGHypAsKhDVQw5mrFZww", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QRKRk5HVADsN1LHygK7q2pA7dWnYKnPpCT", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QSGB4Rd2xhd6UmA9LALTQ4f89Tfsz5VajU", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QNVKrjEq5bZdiDtgo64m5kz87rTHqCwvCP", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QNMDKE7XTujNQkuQorcHXw6hL7qRvyaTjr", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QY6ZGZdi8h5op2VrRXkG1W5Jp3feLwp7ZD", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "Qgwb5SLVGAperXAMoVNBDvGpVAxTVY7f6F", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QNHdGeFJmPcDdN8prPzPL4bk2dpnJ2ZZFr", "level": 4 }, + { "type": "ACCOUNT_LEVEL", "target": "QUXga5K8nzd9EqYtvEesZWEYuA688h6D3d", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QfbX8JJupEw5ckNtU4upQgET35oLTr5e6v", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QRaDef6H2zYfefqLwYGmUg7T6DAqo6DDqc", "level": 3 }, { "type": "ACCOUNT_LEVEL", "target": "QSkiGy3v3MwvGy3aACuyLDv3Xy2AWAYfPS", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QeUc5NfzubZD4eA4eJ7bfXAFraAWc7jVz5", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QfPcwetW3BErP4ySTurxFJSHpNkNXPEhGk", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QU8XJyQEZxSHgrS1XyooWUo5MmruXg36Pe", "level": 3 }, - { "type": "ACCOUNT_LEVEL", "target": "QeDhJRqTyeDmcgGJoms6FHK49ZGVpVahxg", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QibuD4c6gvXgS4iut7q3sXuVb23rgFJq2M", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QTpYQqRyMekaEuECziirzy3HvCVofZS1wJ", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QXv4WiqgryFPi8BgX7RU7gqtAgrVutmU4S", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QawSgZ7i2LLFTKyPxQptk9gN526ihy5yZi", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QMuWNAJ2tbeViHtBUN3yD2KARrrzcanLAd", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QUGo9SErgc6ceB5aBzcSJDNqBkQ9eaCKZS", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QdFZk74skMUu4rKMPEmcSVwR87LNDe6o3Y", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QScBgSw74MquesXmVJxerX3YgyhtShRr4q", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QRWEbzH4niUcu9dL3Yq42X4j89aqQk3qWw", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QYD3kXchZ86vUyJBXNCVQ4LUvTAd6PUZW3", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QhQdzLn36SDgrgoMfvdZAkoWtTUHpB3acJ", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QWL7kZp6Pdd1bhxZ6SXPhVf5g7GParG9CC", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QjgGeEkyiXa43pyqkXxZbvAChQpVYfUyKz", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QbxJvwrEHZs7MDE8rbqBwZAZkcywue5F3W", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QWwrtjBL4ah965XPXHYJhymreC9jyryNLZ", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QjEaMxcBKMsj91ytKe6GdTBJP8Mu1Ru3r4", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QPusqAVBVFGAAeE7RdospttA18AuyLP7sB", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "Qd1Px9vhWuEmF2SbLx3Ez7HhGtifGMa8TJ", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QWuW2YMygVtWieUo6a4yayD1xFDWdnmo5j", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QbYTowTHCr9WzfrR6b8uDfJKwL41nG1vyr", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QNw9xAm9TUerin9QsapCPL9mV6zmoXyJrh", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QSq8y4ZrSbF55ZddWNcw1ett2LDtjQEvNn", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QYuMATkLjz7YB6s4EG1aWCmmmrAPj3W9Ce", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QNiTnonHpXTeUrgNdyYWVDPP4ZdjkLpW72", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QjrCFCi6dqvka4UELg2SHhM2oWnQWepd1o", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QREtYDhP4HkpeCCZroemuGXMGVFoZHH3Lp", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QdXdUxnyKGGo7eEfTcx85oEikNe5nYnuwa", "level": 3 }, + { "type": "ACCOUNT_LEVEL", "target": "QWBFK5h61ZxGfqQpEkwwKTcLAo8t9VWe4K", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QjEAs2or122weKppv5zALzoQzXxbsDjy3f", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QgesuKa3zwx8VAseF1oHZAFHMf29k8ergq", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QUZQPWhrxpze32vGiux6wa85kg9iwuhCDx", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QWinRb65f2g3yBoaZvTrQKQk7CW7vfBgGX", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QQaKBSjAt9RK2bqJoSriR77X4ULstGzrFQ", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QdwSxr3t4hdGHjQFy6EVGR9yGMipefsTuo", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QZ2gi6BhUNpGmrErgJLFuY1WHy6xK1J7qX", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QXYk68x2tiUrDBv8eq6wd4KtBmLHYiC4zR", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QTyokTJrR4b2y76An3BFUEbqQy5vvg76iN", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QisSQZ7Et7Rfzx2SCC2o9UDSeRZWMyFKWc", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QPyx2bNiAnJEjitfeAh8jZXzQVKio2B7Mi", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QeUc5NfzubZD4eA4eJ7bfXAFraAWc7jVz5", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QU8XJyQEZxSHgrS1XyooWUo5MmruXg36Pe", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QfPcwetW3BErP4ySTurxFJSHpNkNXPEhGk", "level": 2 }, { "type": "ACCOUNT_LEVEL", "target": "QQHWFSJpzuDupPfcTvGMRNJp2UGz98Kb7j", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QeDhJRqTyeDmcgGJoms6FHK49ZGVpVahxg", "level": 2 }, { "type": "ACCOUNT_LEVEL", "target": "QdepeWWLMD3LiDRKkKBria29rDhZP9V5RJ", "level": 2 }, - { "type": "ACCOUNT_LEVEL", "target": "QZvHW7amu5DNktsBgaMrR1brHZhhhVwKLW", "level": 2 }, - { "type": "ACCOUNT_LEVEL", "target": "QjrC8NXwR8gFkEauvRwCPxqHroPFqAJbhK", "level": 2 }, { "type": "ACCOUNT_LEVEL", "target": "QWez1VBfYVJ8KFoZ6MhJDzYVLbn5mr38VT", "level": 2 }, { "type": "ACCOUNT_LEVEL", "target": "QYsh2NB6TogqV1iXHmHXcVaWw25WEYA94o", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QfhJM5CpX5MhfjCcopwfw7pgS6w1hVJ49E", "level": 2 }, { "type": "ACCOUNT_LEVEL", "target": "QMMh94Pfs5LVE4xJee1yggViqP1YDdQHT4", "level": 2 }, { "type": "ACCOUNT_LEVEL", "target": "QU9dnN47Nc5KaH7JwNoCZ7TANwCW5VX9iG", "level": 2 }, { "type": "ACCOUNT_LEVEL", "target": "QXoW5M113C3SDUeFdjVVs2m1RT9XtzXS3z", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QjsD7pMh2LpmgYudaaRM8gmzhBC4c9uwyj", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QMozpRT9aUunfmPh7EtQ6LPoth2JFJWBXC", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QeSh3t1AnaRcRThkkUTvvdMEouixCADeVh", "level": 2 }, { "type": "ACCOUNT_LEVEL", "target": "QZxcntxfJimHus9pgfvVVPbpHs5yU7ZMhB", "level": 2 }, - { "type": "ACCOUNT_LEVEL", "target": "Qc2eRuYXtpATrg87Pr1WDXkUBCsgNRYcQF", "level": 2 }, - { "type": "ACCOUNT_LEVEL", "target": "QbEJ5tfeskASVnmLFeKzspuZJJb6cJVPZ4", "level": 2 }, - { "type": "ACCOUNT_LEVEL", "target": "QWvTdm9LU1GSX9q6Rrvgx7xjo2iuV2Gxn1", "level": 2 }, - { "type": "ACCOUNT_LEVEL", "target": "QWuW2YMygVtWieUo6a4yayD1xFDWdnmo5j", "level": 2 }, - { "type": "ACCOUNT_LEVEL", "target": "QbGwYRV3UDek4VNpzoAVVQWfoKjZmm4qPb", "level": 2 }, - { "type": "ACCOUNT_LEVEL", "target": "QYM76r3tuf6FJWz2USqVjwXJrV9tLMz1cj", "level": 2 }, - { "type": "ACCOUNT_LEVEL", "target": "QU9K6pWhkok9mokkPDoCwgSu3j62ECuKLD", "level": 2 }, - { "type": "ACCOUNT_LEVEL", "target": "QZbKMgYBwWGyTDJzoDir2aNqXsFdDp6fS9", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QTtXS6fZGThRLq4qgkwM4ngBYkLoFyZ3bK", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QRBVE5gHumH6RUgEUxJdQ5417NUvc14k3F", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "QPqfuZpmyA6cK6WUFwcGeKH2Te1aegkHBM", "level": 2 }, + { "type": "ACCOUNT_LEVEL", "target": "Qc2eRuYXtpATrg87Pr1WDXkUBCsgNRYcQF", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QbEJ5tfeskASVnmLFeKzspuZJJb6cJVPZ4", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QZjCgcSVvSRsFZeLJz9C5dTa36s3cSKqvB", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QWvTdm9LU1GSX9q6Rrvgx7xjo2iuV2Gxn1", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QZw7tgMttSySNMKfcMrEbdtnqHVrQ9w9fT", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QbGwYRV3UDek4VNpzoAVVQWfoKjZmm4qPb", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QYM76r3tuf6FJWz2USqVjwXJrV9tLMz1cj", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QUdjqijDoyc83K4WcMW1sCn7zLd2t1WTqn", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QU9K6pWhkok9mokkPDoCwgSu3j62ECuKLD", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QZbKMgYBwWGyTDJzoDir2aNqXsFdDp6fS9", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QVEfMEeEHP768c9rEyi3WcH2JQwqheVDe3", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QehM6hQZVkrYAst8WrBVdQiMFfTtDtbKQu", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QY7gQwZKiPYMHYjYASSDBhhAoyYaxmex17", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QgmEtScSZWJmTUAidCZKj6gDr3LznZ6rr4", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "Qa9NXeLAvmaTsKackfDRmm1A9zy7JeEjgV", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QXqAtZJsLU6HFGTzuegjeUbmEW8cGEnYt6", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QZJc1V32oFm8tufB4bk7fa3aepu4EdkeDU", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QVb7P596imucSwDqb5HHEjqpnAre615PbS", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QNMtHRjEWPgZUVCpiC2qE2LyJsxq1BC1Yj", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QUNTxxwr9f47RcwY48ZUP6FmmKnWCsxes5", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QSTDdguUfKe6TaQrik2zq4Xrbu6unxNa9o", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QgsxpySDm1qja6D2EyKuHPiUhyTM1RMk6c", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QaZs97g4Mbq9tXMoBWbhw3jFvBBVkWKS5F", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QWZwi5NUzHuJfg5fh9HzjWRpQc1fmMknAh", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QMb2cAKb2BUxknneuoXQynJ7uzosJ57Top", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QQXgH4CnQCB76BbXhsApu6ShhohFfvoXv7", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QP9vU5yTsBjuTSFxH5Cb9VXYNRHKhMNAJ4", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QXm5e16Lq6dnYwpZJ8Rn2cME3ziHZfRRnp", "level": 1 }, - { "type": "ACCOUNT_LEVEL", "target": "Qa9NXeLAvmaTsKackfDRmm1A9zy7JeEjgV", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "QiQernJdiP4zCECB93v247FUtovkfJyTYm", "level": 1 }, { "type": "ACCOUNT_LEVEL", "target": "Qa4KygekpW1Brr3D66K6rGtS5AY8qkhvD3", "level": 1 }, + { "type": "ACCOUNT_LEVEL", "target": "QSkicapNH35a3UebSxxSMCfntBhwwi6veW", "level": 1 }, + { "type": "GENESIS", "recipient": "QdoLZqB3pY4NgbSpvbsFzBDq2LcShjXsoq", "amount": "263574650.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QMtx2UmUuRZckCmRJRyxdzSAazHP8hU5rA", "amount": "160672815.43629771", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QQKeokRiFCgAhBSdu1DUf5e1LCkgApvrxZ", "amount": "100000078.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QYoRWAxw6CVMeYeWHKJh3csmTVkVzjpdBo", "amount": "100000026.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QMkgf9Y6Ac2TUrynDvyhX69ekpC3P3GQmN", "amount": "99008835.47860426", "assetId": 1 }, { "type": "GENESIS", "recipient": "QWZm17rRXeUehcM4TprVNNRSTHWQmG2bME", "amount": "62663714.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "Qa95hURaNK4kPhDhbdmDFm2wMkkoWFZ4Zz", "amount": "40976709.97984710", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QZjDFrMrgeR9SGL8bprqyiXVtAZMVCXESZ", "amount": "37291276.42323117", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QaWReiLe5tAsTNoq7hMiSGNasJEXTX5bmn", "amount": "31465829.00562504", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QYsLsfwMRBPnunmuWmFkM4hvGsfooY8ssU", "amount": "25303386.66951814", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QgULJXk3qyLDr4EKkz48rxwwvWK7BDL8Ux", "amount": "22476856.86000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QNwedkYs6hToBRPZvBb6naKvDEgB7BeaKi", "amount": "21967101.30582773", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QgP7vQABSDJwuE8VTdVkiNnbkorqWWctQm", "amount": "20442665.63310002", "assetId": 1 }, { "type": "GENESIS", "recipient": "QLgBTDkt7t7WwbTd1RM8iGxu9FexPZcn7C", "amount": "19000025.40000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QQShonrAdJXg4CzhegtynzaBP7S631vKGq", "amount": "16577946.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QcAVj3i3drVkiC9P8FtDgVdYz8Zeu61uNg", "amount": "13142764.62938834", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QLgewDr48AZxWbDbRZ12xEvCePwPj9bMBE", "amount": "12684967.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QPEoMF2dA7NHrHhsSG9zczCFwx9wFdWvzT", "amount": "10033147.61257500", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QWLhUT55hZHgdD7ayEqwHnF9h62dHV45G1", "amount": "9999999.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QjnHejJPyuyTRs7huzcqXtbM6sufWyLf9o", "amount": "9999999.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QjJjjBUJSZAMuYiwTyfJTFthH6SrofjG6d", "amount": "8871800.22712502", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QRh9zNPmz5McxeWx3iCy2xnBRrBoYDZfMJ", "amount": "8739995.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QWGwGBzZG8UeNXJYZq9tjzN6ceriqTgMRd", "amount": "7825760.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QRj4VNEthakckhYpCJMEBhEFk12pa7GPJT", "amount": "7810001.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QbdHzyw6q2hMAhg12JFbXSEcbrj43xNnYG", "amount": "7593814.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QNFWWhmsun3HVUChjck8XqhsQW2tckNxxM", "amount": "7239123.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QeosmemBtE7aosv2QZhq1PTjqpKurKXKzy", "amount": "6185646.80750010", "assetId": 1 }, { "type": "GENESIS", "recipient": "QQM9B3ipQcSvATsxb4vgVuYs9kuxgnuBwG", "amount": "5032347.69657146", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QLu6X6CVhr6tovNR6k9pQijxN4DHiuLeJS", "amount": "4918400.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QPdkHcN8DBLuxaFf4Q4zXNn3rq2G78VgNt", "amount": "4128493.31116798", "assetId": 1 }, { "type": "GENESIS", "recipient": "QMNdPz11XubtvxXLGeiG3PHKaQW67LkZMp", "amount": "4056950.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QhUWSWWFt6vDy2qNFn68JPTPLjyDrzrh4D", "amount": "3220564.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QQ7wKkXyQtkwrgG6zeSHNrnDhXQ6fGUsYS", "amount": "3088411.29750001", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QcxXT317FQi3mq9hrQggw7xZujPX63XCq7", "amount": "2779141.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QMTcDA7v1dbRXHkryn4ppiM9Q7LGZFNkVT", "amount": "2752011.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QTekAqCoXPy5R7NE78GXxjSaXBuekZge88", "amount": "2740816.93000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QVQErjTVBkPTphbyDhPvhHKGX2etNXZsgy", "amount": "1999999.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QNPfWoyuvYaScXuCdiCM2PEzvD7PWybBvh", "amount": "1749402.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QV96D15Y3qM1r55odiDf7j2TTYY8jCMJPs", "amount": "1572208.70562500", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QLsEy8syg8EXttzajE8AWGg3CxccNR6YML", "amount": "1300001.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QLeNqYjzid2oJFL2iVtcHeAkyunuTsHae4", "amount": "1185185.44326193", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QaUhQiyBZpZWSmFo56zRu2XXfZVL4D2xii", "amount": "1033451.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QMrECKgkohx6ZXEMdLzikqBmAkdyHeQDqL", "amount": "997498.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QR1GoYcR3iasGNWtJjeNcZFPf9BH4TjCeC", "amount": "858153.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QMFysMKXLubP21BCYeYiSNP3v5mLhp81Cd", "amount": "676881.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QMdfkckSTcCMKnRRve51SEfZQPVLZg9S7b", "amount": "333086.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QN2UFyKfUsJBHmM5hZrrD2wrwZ1SctSfwQ", "amount": "296438.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QQRUVwMGifreiLv3FuPTTcA1WbsvhH7Mux", "amount": "102825.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QMQAG28pyv2aZVjWbKoRn39Ytir6rLPnTK", "amount": "100745.00000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QgkNZyrj4zAEAwCDZHTLQ7RcbcCTwcNzPL", "amount": "99999.09400001", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QLnyXdhGDVEBmByTtjTZihVE3UnReghNyd", "amount": "78296.75000000", "assetId": 1 }, + { "type": "GENESIS", "recipient": "QTHQ9pFMoraWTCS1tuFzuwWSXu7uVJ18VF", "amount": "40395.00000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QVZAQrQHPD8rePZ5hWKx4uj7Ty4GEBe15D", "amount": "2989.50000000", "assetId": 1 }, { "type": "GENESIS", "recipient": "QPZTxWtCmH6Y6zwwntjnPDfKG6zNKRivqJ", "amount": "1282.61375000", "assetId": 1 }