Search in sources :

Example 6 with TransactionInner

use of snowblossom.proto.TransactionInner in project snowblossom by snowblossomcoin.

the class MemPool method addTransaction.

/**
 * @return true iff this seems to be a new and valid tx
 */
public boolean addTransaction(Transaction tx, boolean p2p_source) throws ValidationException {
    try (MetricLog mlog = new MetricLog()) {
        long t1 = System.nanoTime();
        Validation.checkTransactionBasics(tx, false);
        mlog.set("basic_validation", 1);
        TimeRecord.record(t1, "mempool:tx_validation");
        long t_lock = System.nanoTime();
        synchronized (this) {
            TimeRecord.record(t_lock, "mempool:have_lock");
            mlog.setOperation("add_transaction");
            mlog.setModule("mem_pool");
            mlog.set("added", 0);
            if ((p2p_source) && (!accepts_p2p_tx)) {
                mlog.set("reject_p2p", 1);
                return false;
            }
            ChainHash tx_hash = new ChainHash(tx.getTxHash());
            mlog.set("tx_id", tx_hash.toString());
            if (known_transactions.containsKey(tx_hash)) {
                mlog.set("already_known", 1);
                return false;
            }
            if (known_transactions.size() >= MEM_POOL_MAX) {
                throw new ValidationException("mempool is full");
            }
            TransactionMempoolInfo info = new TransactionMempoolInfo(tx);
            TransactionInner inner = info.inner;
            double tx_ratio = (double) inner.getFee() / (double) tx.toByteString().size();
            mlog.set("fee", inner.getFee());
            mlog.set("fee_ratio", tx_ratio);
            if (tx_ratio < Globals.LOW_FEE) {
                mlog.set("low_fee", 1);
                if (known_transactions.size() >= MEM_POOL_MAX_LOW) {
                    throw new ValidationException("mempool is too full for low fee transactions");
                }
            }
            TreeSet<String> used_outputs = new TreeSet<>();
            TimeRecord.record(t1, "mempool:p1");
            long t3 = System.nanoTime();
            mlog.set("input_count", inner.getInputsCount());
            mlog.set("output_count", inner.getOutputsCount());
            for (TransactionInput in : inner.getInputsList()) {
                String key = HexUtil.getHexString(in.getSrcTxId()) + ":" + in.getSrcTxOutIdx();
                used_outputs.add(key);
                if (claimed_outputs.containsKey(key)) {
                    if (!claimed_outputs.get(key).equals(tx_hash)) {
                        throw new ValidationException("Discarding as double-spend");
                    }
                }
            }
            TimeRecord.record(t3, "mempool:input_proc");
            long output_total = inner.getFee();
            for (TransactionOutput out : inner.getOutputsList()) {
                output_total += out.getValue();
            }
            mlog.set("total_output", output_total);
            if (utxo_for_pri_map != null) {
                long t2 = System.nanoTime();
                TXCluster cluster = buildTXCluster(tx);
                mlog.set("cluster_tx_count", cluster.tx_list.size());
                mlog.set("cluster_tx_size", cluster.total_size);
                TimeRecord.record(t2, "mempool:build_cluster");
                if (cluster == null) {
                    throw new ValidationException("Unable to find a tx cluster that makes this work");
                }
                double ratio = (double) cluster.total_fee / (double) cluster.total_size;
                // Random rnd = new Random();
                // ratio = ratio * 1e9 + rnd.nextDouble();
                long t4 = System.nanoTime();
                priority_map.put(ratio, cluster);
                TimeRecord.record(t4, "mempool:primapput");
            }
            TimeRecord.record(t1, "mempool:p2");
            known_transactions.put(tx_hash, info);
            for (AddressSpecHash spec_hash : info.involved_addresses) {
                address_tx_map.put(spec_hash, tx_hash);
            }
            // Claim outputs used by inputs
            for (String key : used_outputs) {
                claimed_outputs.put(key, tx_hash);
            }
            TimeRecord.record(t1, "mempool:tx_add");
            TimeRecord.record(t1, "mempool:p3");
            for (MemPoolTickleInterface listener : mempool_listener) {
                listener.tickleMemPool(tx, info.involved_addresses);
            }
            mlog.set("added", 1);
            return true;
        }
    }
}
Also used : TransactionOutput(snowblossom.proto.TransactionOutput) MetricLog(duckutil.MetricLog) ByteString(com.google.protobuf.ByteString) TransactionInput(snowblossom.proto.TransactionInput) TransactionInner(snowblossom.proto.TransactionInner)

Aggregations

TransactionInner (snowblossom.proto.TransactionInner)6 TransactionInput (snowblossom.proto.TransactionInput)5 ByteString (com.google.protobuf.ByteString)4 TransactionOutput (snowblossom.proto.TransactionOutput)4 Transaction (snowblossom.proto.Transaction)3 MetricLog (duckutil.MetricLog)1 LinkedList (java.util.LinkedList)1 BlockHeader (snowblossom.proto.BlockHeader)1 RequestTransaction (snowblossom.proto.RequestTransaction)1