Search in sources :

Example 41 with Transaction

use of neo.model.core.Transaction 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 42 with Transaction

use of neo.model.core.Transaction in project neo-java by coranos.

the class BlockDbMapDbImpl method getTransactionWithAccountList.

@Override
public List<Transaction> getTransactionWithAccountList(final UInt160 account) {
    final List<Transaction> transactionList = new ArrayList<>();
    final BTreeMap<byte[], byte[]> transactionByAccountAndIndexMap = getTransactionByAccountAndIndexMap();
    final BTreeMap<byte[], Long> transactionByAccountMaxIndexMap = getTransactionByAccountMaxIndexMap();
    final byte[] accountBa = account.toByteArray();
    final long maxIndex = transactionByAccountMaxIndexMap.get(accountBa);
    for (long ix = 0; ix < maxIndex; ix++) {
        final byte[] accountKeyBa = getAccountKey(accountBa, ix);
        final byte[] ba = transactionByAccountAndIndexMap.get(accountKeyBa);
        final ByteBuffer bb = ByteBuffer.wrap(ba);
        final Transaction transaction = new Transaction(bb);
        transactionList.add(transaction);
    }
    return transactionList;
}
Also used : Transaction(neo.model.core.Transaction) ArrayList(java.util.ArrayList) ByteBuffer(java.nio.ByteBuffer)

Example 43 with Transaction

use of neo.model.core.Transaction in project neo-java by coranos.

the class BlockDbMapDbImpl method updateAssetAndValueByAccountMap.

/**
 * updates the asset and value by account map.
 *
 * @param block
 *            the block to update.
 * @param reverse
 *            if true, reverse the update.
 */
private void updateAssetAndValueByAccountMap(final Block block, final boolean reverse) {
    final BTreeMap<byte[], byte[]> assetAndValueByAccountMap = getAssetAndValueByAccountMap();
    final BTreeMap<byte[], byte[]> transactionByAccountAndIndexMap = getTransactionByAccountAndIndexMap();
    final BTreeMap<byte[], Long> transactionByAccountMaxIndexMap = getTransactionByAccountMaxIndexMap();
    final BTreeMap<byte[], Boolean> transactionOutputSpentStateMap = getTransactionOutputSpentStateMap();
    LOG.debug("updateAssetAndValueByAccountMap STARTED block;{};reverse;{};numberOfAccounts:{}", block.getIndexAsLong(), reverse, assetAndValueByAccountMap.size());
    for (final Transaction t : block.getTransactionList()) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("updateAssetAndValueByAccountMap INTERIM tx:{}", t.getHash());
        }
        for (final CoinReference cr : t.inputs) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("updateAssetAndValueByAccountMap INTERIM cr:{}", cr.toJSONObject());
            }
            final byte[] crBa = cr.toByteArray();
            if (!transactionOutputSpentStateMap.containsKey(crBa)) {
                throw new RuntimeException("referenced transaction output was never a transaction input:" + cr);
            }
            final boolean oldSpendState;
            final boolean newSpendState;
            if (reverse) {
                oldSpendState = true;
                newSpendState = false;
            } else {
                oldSpendState = false;
                newSpendState = true;
            }
            if (transactionOutputSpentStateMap.get(crBa) == oldSpendState) {
                transactionOutputSpentStateMap.put(crBa, newSpendState);
                final UInt256 prevHashReversed = cr.prevHash.reverse();
                final Transaction tiTx = getTransactionWithHash(prevHashReversed);
                if (tiTx == null) {
                    throw new RuntimeException("no transaction with prevHash:" + prevHashReversed + " in block[1] " + block.hash + " index[1] " + block.getIndexAsLong());
                }
                final int prevIndex = cr.prevIndex.asInt();
                if (prevIndex >= tiTx.outputs.size()) {
                    throw new RuntimeException("prevIndex:" + prevIndex + " exceeds output size:" + tiTx.outputs.size() + "; in block[2] " + block.hash + " index[2] " + block.getIndexAsLong());
                }
                final TransactionOutput ti = tiTx.outputs.get(prevIndex);
                final UInt160 input = ti.scriptHash;
                final byte[] inputBa = input.toByteArray();
                final Map<UInt256, Fixed8> accountAssetValueMap = ensureAccountExists(assetAndValueByAccountMap, inputBa);
                if (LOG.isDebugEnabled()) {
                    LOG.debug("TI beforeMap {}", accountAssetValueMap);
                }
                if (!accountAssetValueMap.containsKey(ti.assetId)) {
                    accountAssetValueMap.put(ti.assetId, ModelUtil.FIXED8_ZERO);
                }
                final Fixed8 oldValue = accountAssetValueMap.get(ti.assetId);
                final Fixed8 newValue;
                if (reverse) {
                    newValue = ModelUtil.add(ti.value, oldValue);
                } else {
                    newValue = ModelUtil.subtract(ti.value, oldValue);
                }
                if (LOG.isDebugEnabled()) {
                    LOG.debug("updateAssetAndValueByAccountMap INTERIM input;{};", ModelUtil.scriptHashToAddress(input));
                    LOG.debug("updateAssetAndValueByAccountMap INTERIM ti.assetId:{} oldValue:{};", ti.assetId, oldValue);
                    LOG.debug("updateAssetAndValueByAccountMap INTERIM ti.assetId:{} to.value:{};", ti.assetId, ti.value);
                    LOG.debug("updateAssetAndValueByAccountMap INTERIM ti.assetId:{} newValue:{};", ti.assetId, newValue);
                }
                if (newValue.equals(ModelUtil.FIXED8_ZERO)) {
                    accountAssetValueMap.remove(ti.assetId);
                } else {
                    accountAssetValueMap.put(ti.assetId, newValue);
                }
                if (accountAssetValueMap.isEmpty()) {
                    assetAndValueByAccountMap.remove(inputBa);
                } else {
                    putAssetValueMap(assetAndValueByAccountMap, inputBa, accountAssetValueMap);
                }
                if (LOG.isDebugEnabled()) {
                    LOG.debug("TI afterMap {}", ensureAccountExists(assetAndValueByAccountMap, inputBa));
                }
            } else {
                if (reverse) {
                    throw new RuntimeException("referenced transaction output is not already spent:" + cr);
                } else {
                    throw new RuntimeException("referenced transaction output is already spent:" + cr);
                }
            }
        }
        try {
            for (int outputIx = 0; outputIx < t.outputs.size(); outputIx++) {
                final TransactionOutput to = t.outputs.get(outputIx);
                if (LOG.isDebugEnabled()) {
                    LOG.debug("updateAssetAndValueByAccountMap INTERIM to:{}", to.toJSONObject());
                }
                final UInt160 output = to.scriptHash;
                final byte[] outputBa = output.toByteArray();
                final Map<UInt256, Fixed8> accountAssetValueMap = ensureAccountExists(assetAndValueByAccountMap, outputBa);
                if (LOG.isDebugEnabled()) {
                    LOG.debug("TO beforeMap {}", accountAssetValueMap);
                }
                if (!accountAssetValueMap.containsKey(to.assetId)) {
                    accountAssetValueMap.put(to.assetId, ModelUtil.FIXED8_ZERO);
                }
                final Fixed8 oldValue = accountAssetValueMap.get(to.assetId);
                if (LOG.isDebugEnabled()) {
                    LOG.debug("updateAssetAndValueByAccountMap INTERIM output;{};", ModelUtil.scriptHashToAddress(output));
                    LOG.debug("updateAssetAndValueByAccountMap INTERIM to.assetId:{} oldValue:{};", to.assetId, oldValue);
                    LOG.debug("updateAssetAndValueByAccountMap INTERIM to.assetId:{} to.value:{};", to.assetId, to.value);
                }
                final Fixed8 newValue;
                if (reverse) {
                    newValue = ModelUtil.subtract(to.value, oldValue);
                } else {
                    newValue = ModelUtil.add(oldValue, to.value);
                }
                accountAssetValueMap.put(to.assetId, newValue);
                if (accountAssetValueMap.isEmpty()) {
                    assetAndValueByAccountMap.remove(outputBa);
                } else {
                    putAssetValueMap(assetAndValueByAccountMap, outputBa, accountAssetValueMap);
                }
                if (LOG.isDebugEnabled()) {
                    LOG.debug("updateAssetAndValueByAccountMap INTERIM to.assetId:{} newValue:{};", to.assetId, newValue);
                    LOG.debug("TO afterMap {}", ensureAccountExists(assetAndValueByAccountMap, outputBa));
                }
                final CoinReference cr = new CoinReference(t.getHash().reverse(), new UInt16(outputIx));
                if (reverse) {
                    transactionOutputSpentStateMap.remove(cr.toByteArray());
                } else {
                    transactionOutputSpentStateMap.put(cr.toByteArray(), false);
                }
            }
            final byte[] tBa = t.toByteArray();
            final long index;
            if (transactionByAccountMaxIndexMap.containsKey(tBa)) {
                index = transactionByAccountMaxIndexMap.get(tBa);
            } else {
                index = 0;
            }
            transactionByAccountMaxIndexMap.put(tBa, index + 1);
            final byte[] accountKeyBa = getAccountKey(tBa, index);
            transactionByAccountAndIndexMap.put(accountKeyBa, tBa);
        } catch (final RuntimeException e) {
            final String msg = "error processing transaction type " + t.type + " hash " + t.getHash();
            throw new RuntimeException(msg, e);
        }
    }
    LOG.debug("updateAssetAndValueByAccountMap SUCCESS block;{};numberOfAccounts:{}", block.getIndexAsLong(), assetAndValueByAccountMap.size());
}
Also used : CoinReference(neo.model.core.CoinReference) TransactionOutput(neo.model.core.TransactionOutput) Transaction(neo.model.core.Transaction) UInt160(neo.model.bytes.UInt160) Fixed8(neo.model.bytes.Fixed8) UInt16(neo.model.bytes.UInt16) UInt256(neo.model.bytes.UInt256)

Example 44 with Transaction

use of neo.model.core.Transaction 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)

Example 45 with Transaction

use of neo.model.core.Transaction in project neo-java by coranos.

the class RpcServerUtil method getAddressAssetMap.

/**
 * returns the address asset map.
 *
 * @param blockDb
 *            the block database to use.
 * @param transaction
 *            the transaction to use.
 * @return the address asset map.
 */
public static Map<UInt160, Map<UInt256, Long>> getAddressAssetMap(final BlockDb blockDb, final Transaction transaction) {
    final Map<UInt160, Map<UInt256, Long>> friendAssetMap = new TreeMap<>();
    for (final CoinReference cr : transaction.inputs) {
        final UInt256 prevHashReversed = cr.prevHash.reverse();
        final Transaction tiTx = blockDb.getTransactionWithHash(prevHashReversed);
        if (tiTx == null) {
            throw new RuntimeException("no transaction with prevHash:" + prevHashReversed);
        }
        final TransactionOutput ti = tiTx.outputs.get(cr.prevIndex.asInt());
        final UInt160 input = ti.scriptHash;
        if ((ti.assetId.equals(ModelUtil.NEO_HASH)) || (ti.assetId.equals(ModelUtil.GAS_HASH))) {
            MapUtil.increment(friendAssetMap, input, ti.assetId, ti.value.value, TreeMap.class);
        }
    }
    for (final TransactionOutput to : transaction.outputs) {
        final UInt160 output = to.scriptHash;
        if ((to.assetId.equals(ModelUtil.NEO_HASH)) || (to.assetId.equals(ModelUtil.GAS_HASH))) {
            MapUtil.increment(friendAssetMap, output, to.assetId, -to.value.value, TreeMap.class);
        }
    }
    return friendAssetMap;
}
Also used : CoinReference(neo.model.core.CoinReference) TransactionOutput(neo.model.core.TransactionOutput) Transaction(neo.model.core.Transaction) UInt160(neo.model.bytes.UInt160) TreeMap(java.util.TreeMap) Map(java.util.Map) TreeMap(java.util.TreeMap) UInt256(neo.model.bytes.UInt256)

Aggregations

Transaction (neo.model.core.Transaction)49 JSONObject (org.json.JSONObject)26 Block (neo.model.core.Block)25 JSONArray (org.json.JSONArray)19 TransactionOutput (neo.model.core.TransactionOutput)17 Test (org.junit.Test)14 UInt256 (neo.model.bytes.UInt256)13 TreeMap (java.util.TreeMap)12 BlockDb (neo.model.db.BlockDb)9 Map (java.util.Map)8 Fixed8 (neo.model.bytes.Fixed8)8 UInt160 (neo.model.bytes.UInt160)8 CoinReference (neo.model.core.CoinReference)8 ArrayList (java.util.ArrayList)6 IOException (java.io.IOException)5 LocalNodeData (neo.network.model.LocalNodeData)5 Timestamp (java.sql.Timestamp)4 UInt16 (neo.model.bytes.UInt16)4 List (java.util.List)3 TreeSet (java.util.TreeSet)3