public void putInternal(Transaction tx, Sha256Hash block_hash, StatusContext ctx) { if (block_hash == null) { ctx.setStatus("TX_SERIALIZE"); SerializedTransaction s_tx = new SerializedTransaction(tx); ctx.setStatus("TX_PUT"); // System.out.println("Transaction " + tx.getHash() + " " + Util.measureSerialization(s_tx)); file_db.getTransactionMap().put(tx.getHash(), s_tx); } // putTxOutSpents(tx); boolean confirmed = (block_hash != null); ctx.setStatus("TX_GET_ADDR"); Collection<String> addrs = getAllAddresses(tx, confirmed); Random rnd = new Random(); ctx.setStatus("TX_SAVE_ADDRESS"); file_db.addAddressesToTxMap(addrs, tx.getHash()); imported_transactions.incrementAndGet(); int h = -1; if (block_hash != null) { ctx.setStatus("TX_GET_HEIGHT"); h = block_store.getHeight(block_hash); } ctx.setStatus("TX_NOTIFY"); jelly.getElectrumNotifier().notifyNewTransaction(tx, addrs, h); ctx.setStatus("TX_DONE"); }
private void waitForBlockStored(Sha256Hash hash) { if (hash.toString().equals("0000000000000000000000000000000000000000000000000000000000000000")) return; try { if (file_db.getBlockMap().containsKey(hash)) return; } finally { } Semaphore block_wait_sem = null; synchronized (in_progress) { block_wait_sem = in_progress.get(hash); if (block_wait_sem == null) { block_wait_sem = new Semaphore(0); in_progress.put(hash, block_wait_sem); } } try { // System.out.println("Waiting for " + hash); block_wait_sem.acquire(1); } catch (java.lang.InterruptedException e) { throw new RuntimeException(e); } }
public void checkConsistency() throws com.google.bitcoin.store.BlockStoreException { StoredBlock head = block_store.getChainHead(); StoredBlock curr_block = head; Sha256Hash genisis_hash = params.getGenesisBlock().getHash(); int checked = 0; while (true) { Sha256Hash curr_hash = curr_block.getHeader().getHash(); if (curr_block.getHeight() % 10000 == 0) { System.out.println("Block: " + curr_block.getHeight()); } if (!file_db.getBlockMap().containsKey(curr_hash)) { throw new RuntimeException("Missing block: " + curr_hash); } checked++; // if (checked > 20) return; if (curr_hash.equals(genisis_hash)) return; curr_block = curr_block.getPrev(block_store); } }
public Transaction getTransaction(Sha256Hash hash) { Transaction tx = null; synchronized (transaction_cache) { tx = transaction_cache.get(hash); } if (tx == null) { SerializedTransaction s_tx = file_db.getTransactionMap().get(hash); if (s_tx != null) { tx = s_tx.getTx(params); synchronized (transaction_cache) { transaction_cache.put(hash, SerializedTransaction.scrubTransaction(params, tx)); } } } return tx; }
private void putInternal(Block block, StatusContext ctx) { long t1 = System.currentTimeMillis(); Sha256Hash hash = block.getHash(); ctx.setStatus("BLOCK_CHECK_EXIST"); if (file_db.getBlockMap().containsKey(hash)) { imported_blocks.incrementAndGet(); return; } // Mark block as in progress Semaphore block_wait_sem; synchronized (in_progress) { block_wait_sem = in_progress.get(hash); if (block_wait_sem == null) { block_wait_sem = new Semaphore(0); in_progress.put(hash, block_wait_sem); } } // Kick off threaded storage of transactions int size = 0; ctx.setStatus("BLOCK_TX_CACHE_INSERT"); synchronized (transaction_cache) { for (Transaction tx : block.getTransactions()) { transaction_cache.put(tx.getHash(), SerializedTransaction.scrubTransaction(params, tx)); } } ctx.setStatus("BLOCK_TX_ENQUE"); LinkedList<Sha256Hash> tx_list = new LinkedList<Sha256Hash>(); Collection<Map.Entry<String, Sha256Hash>> addrTxLst = new LinkedList<Map.Entry<String, Sha256Hash>>(); Map<Sha256Hash, SerializedTransaction> txs_map = new HashMap<Sha256Hash, SerializedTransaction>(); for (Transaction tx : block.getTransactions()) { imported_transactions.incrementAndGet(); Collection<String> addrs = getAllAddresses(tx, true); for (String addr : addrs) { addrTxLst.add( new java.util.AbstractMap.SimpleEntry<String, Sha256Hash>(addr, tx.getHash())); } txs_map.put(tx.getHash(), new SerializedTransaction(tx)); tx_list.add(tx.getHash()); size++; } ctx.setStatus("TX_SAVEALL"); file_db.getTransactionMap().putAll(txs_map); ctx.setStatus("BLOCK_TX_MAP_ADD"); file_db.addTxsToBlockMap(tx_list, hash); ctx.setStatus("ADDR_SAVEALL"); file_db.addAddressesToTxMap(addrTxLst); int h = block_store.getHeight(hash); for (Transaction tx : block.getTransactions()) { Collection<String> addrs = getAllAddresses(tx, true); ctx.setStatus("TX_NOTIFY"); jelly.getElectrumNotifier().notifyNewTransaction(tx, addrs, h); ctx.setStatus("TX_DONE"); } // Once all transactions are in, check for prev block in this store ctx.setStatus("BLOCK_WAIT_PREV"); Sha256Hash prev_hash = block.getPrevBlockHash(); waitForBlockStored(prev_hash); // System.out.println("Block " + hash + " " + Util.measureSerialization(new // SerializedBlock(block))); ctx.setStatus("BLOCK_SAVE"); file_db.getBlockMap().put(hash, new SerializedBlock(block)); block_wait_sem.release(1024); boolean wait_for_utxo = false; if (jelly.isUpToDate() && jelly.getUtxoTrieMgr().isUpToDate()) { wait_for_utxo = true; } jelly.getUtxoTrieMgr().notifyBlock(wait_for_utxo); if (wait_for_utxo) { jelly.getEventLog().alarm("UTXO root hash: " + jelly.getUtxoTrieMgr().getRootHash()); } jelly.getElectrumNotifier().notifyNewBlock(block); long t2 = System.currentTimeMillis(); DecimalFormat df = new DecimalFormat("0.000"); double sec = (t2 - t1) / 1000.0; if (h % block_print_every == 0) { jelly .getEventLog() .alarm( "Saved block: " + hash + " - " + h + " - " + size + " (" + df.format(sec) + " seconds)"); } jelly .getEventLog() .log( "Saved block: " + hash + " - " + h + " - " + size + " (" + df.format(sec) + " seconds)"); imported_blocks.incrementAndGet(); }