Search in sources :

Example 1 with BTreeMap

use of org.mapdb.BTreeMap in project neo-java by coranos.

the class BlockDbMapDbImpl method validate.

@Override
public void validate() {
    LOG.info("STARTED validate");
    try {
        final Block block0 = getBlock(0, false);
        if (!block0.hash.equals(GenesisBlockUtil.GENESIS_HASH)) {
            throw new RuntimeException("height 0 block hash \"" + block0.hash.toHexString() + "\" does not match genesis block hash \"" + GenesisBlockUtil.GENESIS_HASH.toHexString() + "\".");
        }
        long lastInfoMs = System.currentTimeMillis();
        long blockHeight = 0;
        long lastGoodBlockIndex = -1;
        final long maxBlockCount = getBlockCount();
        boolean blockHeightNoLongerValid = false;
        final String maxBlockCountStr;
        if (LOG.isDebugEnabled() || LOG.isErrorEnabled()) {
            maxBlockCountStr = NumberFormat.getIntegerInstance().format(maxBlockCount);
        } else {
            maxBlockCountStr = null;
        }
        LOG.info("INTERIM validate, clear account list STARTED");
        final BTreeMap<byte[], byte[]> assetAndValueByAccountMap = getAssetAndValueByAccountMap();
        assetAndValueByAccountMap.clear();
        LOG.info("INTERIM validate, clear account list SUCCESS");
        LOG.info("INTERIM validate, clear transaction output state STARTED");
        getTransactionByAccountAndIndexMap().clear();
        getTransactionByAccountMaxIndexMap().clear();
        LOG.info("INTERIM validate, clear  transaction output state SUCCESS");
        while (blockHeight < maxBlockCount) {
            final String blockHeightStr;
            if (LOG.isDebugEnabled() || LOG.isErrorEnabled()) {
                blockHeightStr = NumberFormat.getIntegerInstance().format(blockHeight);
            } else {
                blockHeightStr = null;
            }
            LOG.debug("INTERIM DEBUG validate {} of {} STARTED ", blockHeightStr, maxBlockCountStr);
            final Block block = getBlock(blockHeight, true);
            if (block == null) {
                LOG.error("INTERIM validate {} of {} FAILURE, block not found in blockchain.", blockHeightStr, maxBlockCountStr);
                blockHeightNoLongerValid = true;
            } else if ((blockHeight != 0) && (!containsBlockWithHash(block.prevHash))) {
                LOG.error("INTERIM validate {} of {} FAILURE, prevHash {} not found in blockchain.", blockHeightStr, maxBlockCountStr, block.prevHash.toHexString());
                deleteBlockAtHeight(blockHeight);
                blockHeightNoLongerValid = true;
            } else if (block.getIndexAsLong() != blockHeight) {
                LOG.error("INTERIM validate {} of {} FAILURE, indexAsLong {} does not match blockchain.", blockHeightStr, maxBlockCountStr, block.getIndexAsLong());
                deleteBlockAtHeight(blockHeight);
                blockHeightNoLongerValid = true;
            } else if (blockHeightNoLongerValid) {
                LOG.error("INTERIM validate {} of {} FAILURE, block height tainted.", blockHeightStr, maxBlockCountStr, block.getIndexAsLong());
                deleteBlockAtHeight(blockHeight);
            } else {
                if (System.currentTimeMillis() > (lastInfoMs + 30000)) {
                    final String numberOfAccountsStr = NumberFormat.getIntegerInstance().format(assetAndValueByAccountMap.size());
                    LOG.info("INTERIM INFO  validate {} of {} SUCCESS, number of accounts:{}; date:{}", blockHeightStr, maxBlockCountStr, numberOfAccountsStr, block.getTimestamp());
                    lastInfoMs = System.currentTimeMillis();
                } else {
                    LOG.debug("INTERIM DEBUG validate {} of {} SUCCESS.", blockHeightStr, maxBlockCountStr);
                }
                final long blockIndex = block.getIndexAsLong();
                int transactionIndex = 0;
                final Map<ByteBuffer, byte[]> txKeyByTxHashMap = new TreeMap<>();
                for (final Transaction transaction : block.getTransactionList()) {
                    final byte[] transactionKeyBa = getTransactionKey(blockIndex, transactionIndex);
                    txKeyByTxHashMap.put(ByteBuffer.wrap(transaction.getHash().toByteArray()), transactionKeyBa);
                    transactionIndex++;
                }
                putWithByteBufferKey(TRANSACTION_KEY_BY_HASH, txKeyByTxHashMap);
                try {
                    updateAssetAndValueByAccountMap(block, false);
                } catch (final Exception e) {
                    throw new RuntimeException("validate: error updating assets for block [" + block.getIndexAsLong() + "]" + block.hash, e);
                }
                lastGoodBlockIndex = block.getIndexAsLong();
            }
            final boolean forceSynch = (lastGoodBlockIndex % BLOCK_FORCE_SYNCH_INTERVAL) == 0;
            if (forceSynch) {
                LOG.info("INTERIM validate, partial commit STARTED index {}", lastGoodBlockIndex);
                commitValidation(lastGoodBlockIndex);
                LOG.info("INTERIM validate, partial commit SUCCESS index {}", lastGoodBlockIndex);
            }
            blockHeight++;
        }
        LOG.info("INTERIM validate, commit STARTED index {}", lastGoodBlockIndex);
        commitValidation(lastGoodBlockIndex);
        LOG.info("INTERIM validate, commit SUCCESS index {}", lastGoodBlockIndex);
        LOG.info("SUCCESS validate");
    } catch (final Exception e) {
        LOG.error("FAILURE validate", e);
        db.rollback();
        throw new RuntimeException(e);
    }
}
Also used : Transaction(neo.model.core.Transaction) Block(neo.model.core.Block) Map(java.util.Map) TreeMap(java.util.TreeMap) BTreeMap(org.mapdb.BTreeMap) NotImplementedException(org.apache.commons.lang3.NotImplementedException) SQLException(java.sql.SQLException) IOException(java.io.IOException)

Example 2 with BTreeMap

use of org.mapdb.BTreeMap in project neo-java by coranos.

the class BlockDbMapDbImpl method put.

@Override
public void put(final boolean forceSynch, final Block... blocks) {
    synchronized (this) {
        if (closed) {
            return;
        }
    }
    if (LOG.isDebugEnabled()) {
        LOG.debug("STARTED put, {} blocks", NumberFormat.getIntegerInstance().format(blocks.length));
    }
    try {
        final BTreeMap<byte[], Long> blockIndexByHashMap = getBlockIndexByHashMap();
        final BTreeMap<Long, byte[]> blockHeaderByIndexMap = getBlockHeaderByIndexMap();
        for (final Block block : blocks) {
            synchronized (this) {
                if (closed) {
                    db.rollback();
                    return;
                }
            }
            final long blockIndex = block.getIndexAsLong();
            final long maxBlockIndex = getMaxBlockIndex();
            final boolean duplicateBlock;
            if ((blockIndex <= maxBlockIndex) && (blockIndex != 0) && (maxBlockIndex != 0)) {
                duplicateBlock = true;
            } else {
                duplicateBlock = false;
            }
            if (duplicateBlock) {
                LOG.error("duplicate block,blockIndex:{};maxBlockIndex:{};hash:{};", blockIndex, maxBlockIndex, block.hash);
            } else {
                final byte[] prevHashBa = block.prevHash.toByteArray();
                ArrayUtils.reverse(prevHashBa);
                blockIndexByHashMap.put(block.hash.toByteArray(), blockIndex);
                blockHeaderByIndexMap.put(blockIndex, block.toHeaderByteArray());
                int transactionIndex = 0;
                final Map<Long, List<byte[]>> txKeyByBlockIxMap = new TreeMap<>();
                final Map<ByteBuffer, byte[]> txByKeyMap = new TreeMap<>();
                final Map<ByteBuffer, byte[]> txKeyByTxHashMap = new TreeMap<>();
                txKeyByBlockIxMap.put(blockIndex, new ArrayList<>());
                for (final Transaction transaction : block.getTransactionList()) {
                    final byte[] transactionBaseBa = transaction.toByteArray();
                    final byte[] transactionKeyBa = getTransactionKey(blockIndex, transactionIndex);
                    putList(txKeyByBlockIxMap, blockIndex, transactionKeyBa);
                    final ByteBuffer transactionKeyBb = ByteBuffer.wrap(transactionKeyBa);
                    txByKeyMap.put(transactionKeyBb, transactionBaseBa);
                    txKeyByTxHashMap.put(ByteBuffer.wrap(transaction.getHash().toByteArray()), transactionKeyBa);
                    transactionIndex++;
                }
                putWithByteBufferKey(TRANSACTION_KEY_BY_HASH, txKeyByTxHashMap);
                putWithByteBufferKey(TRANSACTION_BY_KEY, txByKeyMap);
                putWithLongKey(TRANSACTION_KEYS_BY_BLOCK_INDEX, toByteBufferValue(txKeyByBlockIxMap));
                try {
                    updateAssetAndValueByAccountMap(block, false);
                } catch (final Exception e) {
                    throw new RuntimeException("put: error updating assets for block " + block.hash, e);
                }
                updateMaxBlockIndex(blockIndex);
            }
        }
        db.commit();
    } catch (final Exception e) {
        LOG.error("FAILURE put, {} blocks", NumberFormat.getIntegerInstance().format(blocks.length));
        LOG.error("FAILURE put", e);
        db.rollback();
        throw new RuntimeException(e);
    }
    if (LOG.isDebugEnabled()) {
        LOG.debug("SUCCESS put, {} blocks", NumberFormat.getIntegerInstance().format(blocks.length));
    }
}
Also used : TreeMap(java.util.TreeMap) BTreeMap(org.mapdb.BTreeMap) ByteBuffer(java.nio.ByteBuffer) NotImplementedException(org.apache.commons.lang3.NotImplementedException) SQLException(java.sql.SQLException) IOException(java.io.IOException) Transaction(neo.model.core.Transaction) Block(neo.model.core.Block) ArrayList(java.util.ArrayList) List(java.util.List)

Example 3 with BTreeMap

use of org.mapdb.BTreeMap in project neo-java by coranos.

the class BlockDbMapDbImpl method getAccountAssetValueMap.

@Override
public Map<UInt160, Map<UInt256, Fixed8>> getAccountAssetValueMap() {
    LOG.info("getAccountAssetValueMap STARTED");
    final Map<UInt160, Map<UInt256, Fixed8>> accountAssetValueMap = new TreeMap<>();
    final BTreeMap<byte[], byte[]> assetAndValueByAccountMap = getAssetAndValueByAccountMap();
    LOG.info("getAccountAssetValueMap INTERIM assetAndValueByAccountMap.size:{};", assetAndValueByAccountMap.size());
    for (final byte[] key : assetAndValueByAccountMap.getKeys()) {
        final byte[] value = assetAndValueByAccountMap.get(key);
        final UInt160 account = new UInt160(key);
        final Map<UInt256, Fixed8> map = getAssetValueMapFromByteArray(value);
        accountAssetValueMap.put(account, map);
    }
    LOG.info("getAccountAssetValueMap SUCCESS, count:{}", accountAssetValueMap.size());
    return accountAssetValueMap;
}
Also used : UInt160(neo.model.bytes.UInt160) Fixed8(neo.model.bytes.Fixed8) TreeMap(java.util.TreeMap) BTreeMap(org.mapdb.BTreeMap) Map(java.util.Map) TreeMap(java.util.TreeMap) BTreeMap(org.mapdb.BTreeMap) UInt256(neo.model.bytes.UInt256)

Example 4 with BTreeMap

use of org.mapdb.BTreeMap in project neo-java by coranos.

the class BlockDbMapDbImpl method getUnspentTransactionOutputListMap.

@Override
public Map<UInt256, Map<TransactionOutput, CoinReference>> getUnspentTransactionOutputListMap(final UInt160 account) {
    final List<Transaction> transactionList = getTransactionWithAccountList(account);
    final BTreeMap<byte[], Boolean> transactionOutputSpentStateMap = getTransactionOutputSpentStateMap();
    final Map<UInt256, Map<TransactionOutput, CoinReference>> assetIdTxoMap = new TreeMap<>();
    final BTreeMap<byte[], byte[]> txKeyByHashMap = getTransactionKeyByTransactionHashMap();
    for (final Transaction transaction : transactionList) {
        final byte[] hashBa = transaction.getHash().toByteArray();
        final byte[] txKeyBa = txKeyByHashMap.get(hashBa);
        for (final TransactionOutput to : transaction.outputs) {
            if (to.scriptHash.equals(account)) {
                final byte[] toBa = to.toByteArray();
                if (transactionOutputSpentStateMap.containsKey(toBa)) {
                    if (transactionOutputSpentStateMap.get(toBa) == true) {
                        if (!assetIdTxoMap.containsKey(to.assetId)) {
                            assetIdTxoMap.put(to.assetId, new TreeMap<>());
                        }
                        final int txIx = getTransactionIndexInBlockFromTransactionKey(txKeyBa);
                        final CoinReference cr = new CoinReference(transaction.getHash(), new UInt16(txIx));
                        assetIdTxoMap.get(to.assetId).put(to, cr);
                    }
                }
            }
        }
    }
    return assetIdTxoMap;
}
Also used : CoinReference(neo.model.core.CoinReference) TransactionOutput(neo.model.core.TransactionOutput) TreeMap(java.util.TreeMap) BTreeMap(org.mapdb.BTreeMap) Transaction(neo.model.core.Transaction) UInt16(neo.model.bytes.UInt16) Map(java.util.Map) TreeMap(java.util.TreeMap) BTreeMap(org.mapdb.BTreeMap) UInt256(neo.model.bytes.UInt256)

Aggregations

TreeMap (java.util.TreeMap)4 BTreeMap (org.mapdb.BTreeMap)4 Map (java.util.Map)3 Transaction (neo.model.core.Transaction)3 IOException (java.io.IOException)2 SQLException (java.sql.SQLException)2 UInt256 (neo.model.bytes.UInt256)2 Block (neo.model.core.Block)2 NotImplementedException (org.apache.commons.lang3.NotImplementedException)2 ByteBuffer (java.nio.ByteBuffer)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Fixed8 (neo.model.bytes.Fixed8)1 UInt16 (neo.model.bytes.UInt16)1 UInt160 (neo.model.bytes.UInt160)1 CoinReference (neo.model.core.CoinReference)1 TransactionOutput (neo.model.core.TransactionOutput)1