Ejemplo n.º 1
0
  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();
  }
Ejemplo n.º 2
0
  private void processInMessage(JSONObject msg) throws Exception {
    long idx = msg.optLong("id", -1);
    Object id = msg.opt("id");
    try {

      if (!msg.has("method")) {
        System.out.println("Unknown message: " + msg.toString());
        return;
      }
      String method = msg.getString("method");
      if (method.equals("server.version")) {
        JSONObject reply = new JSONObject();
        reply.put("id", id);
        reply.put("result", "0.9");
        reply.put("jelectrum", JELECTRUM_VERSION);
        version_info = msg.get("params").toString();
        sendMessage(reply);
      } else if (method.equals("server.banner")) {
        JSONObject reply = new JSONObject();
        reply.put("id", id);
        reply.put("result", "Jelectrum");
        sendMessage(reply);
      } else if (method.equals("blockchain.headers.subscribe")) {
        // Should send this on each new block:
        // {"id": 1, "result": {"nonce": 3114737334, "prev_block_hash":
        // "000000000000000089e1f388af7cda336b6241b3f0b0ca36def7a8f22e44d39b", "timestamp":
        // 1387995813, "merkle_root":
        // "0debf5bd535624a955d229337a9bf3da5f370cc5a1f5fbee7261b0bdd0bd0f10", "block_height":
        // 276921, "version": 2, "bits": 419668748}}

        jelectrum.getElectrumNotifier().registerBlockchainHeaders(this, id, true);

      } else if (method.equals("blockchain.numblocks.subscribe")) {
        // Should send this on each new block:
        // {"id": 1, "result": {"nonce": 3114737334, "prev_block_hash":
        // "000000000000000089e1f388af7cda336b6241b3f0b0ca36def7a8f22e44d39b", "timestamp":
        // 1387995813, "merkle_root":
        // "0debf5bd535624a955d229337a9bf3da5f370cc5a1f5fbee7261b0bdd0bd0f10", "block_height":
        // 276921, "version": 2, "bits": 419668748}}

        jelectrum.getElectrumNotifier().registerBlockCount(this, id, true);

      } else if (method.equals("blockchain.address.get_history")) {
        // {"id": 29, "result": [{"tx_hash":
        // "fc054ede2383904323d9b54991693b9150bb1a0a7cd3c344afb883d3ffc093f4", "height": 274759},
        // {"tx_hash": "9dc9363fe032e08630057edb61488fc8fa9910d8b21f02eb1b12ef2928c88550", "height":
        // 274709}]}

        JSONArray params = msg.getJSONArray("params");
        String address = params.getString(0);
        jelectrum.getElectrumNotifier().sendAddressHistory(this, id, address);

      } else if (method.equals("blockchain.address.subscribe")) {
        // the result is
        // sha256(fc054ede2383904323d9b54991693b9150bb1a0a7cd3c344afb883d3ffc093f4:274759:7bb11e62ceb5c9e918d9de541ec8d5d215353c6bbf2fcb32b300ec641f3a0b3f:274708:)
        // tx:height:tx:height:
        // or null if no transactions

        JSONArray params = msg.getJSONArray("params");
        String address = params.getString(0);

        subscription_count.getAndIncrement();
        if (first_address == null) {
          first_address = address;
        }

        jelectrum.getElectrumNotifier().registerBlockchainAddress(this, id, true, address);

      } else if (method.equals("server.peers.subscribe")) {
        JSONObject reply = new JSONObject();
        JSONArray lst = new JSONArray();
        reply.put("id", id);
        reply.put("result", lst);
        sendMessage(reply);
      } else if (method.equals("blockchain.transaction.get")) {
        JSONObject reply = new JSONObject();
        reply.put("id", id);

        JSONArray params = msg.getJSONArray("params");

        Sha256Hash hash = new Sha256Hash(params.getString(0));

        Transaction tx = jelectrum.getImporter().getTransaction(hash);
        if (tx == null) {
          reply.put("error", "unknown transaction");
        } else {
          byte buff[] = tx.bitcoinSerialize();
          reply.put("result", Util.getHexString(buff));
        }

        sendMessage(reply);
      } else if (method.equals("blockchain.block.get_header")) {
        JSONObject reply = new JSONObject();
        reply.put("id", id);

        JSONArray arr = msg.getJSONArray("params");
        int height = arr.getInt(0);

        Sha256Hash block_hash = jelectrum.getBlockChainCache().getBlockHashAtHeight(height);
        StoredBlock blk = jelectrum.getDB().getBlockStoreMap().get(block_hash);

        JSONObject result = new JSONObject();
        jelectrum.getElectrumNotifier().populateBlockData(blk, result);

        reply.put("result", result);

        sendMessage(reply);

      } else if (method.equals("blockchain.transaction.broadcast")) {
        JSONArray arr = msg.getJSONArray("params");
        String hex = arr.getString(0);

        byte[] tx_data = new Hex().decode(hex.getBytes());
        Transaction tx = new Transaction(jelectrum.getNetworkParameters(), tx_data);

        // jelectrum.getPeerGroup().broadcastTransaction(tx);
        JSONObject res = jelectrum.getBitcoinRPC().submitTransaction(hex);

        JSONObject reply = new JSONObject();

        reply.put("id", id);
        reply.put("result", tx.getHash().toString());
        sendMessage(reply);

        jelectrum.getImporter().saveTransaction(tx);

      } else if (method.equals("blockchain.transaction.get_merkle")) {
        JSONObject reply = new JSONObject();
        reply.put("id", id);

        JSONArray arr = msg.getJSONArray("params");
        Sha256Hash tx_hash = new Sha256Hash(arr.getString(0));
        int height = arr.getInt(1);

        Sha256Hash block_hash = jelectrum.getBlockChainCache().getBlockHashAtHeight(height);
        Block blk =
            jelectrum
                .getDB()
                .getBlockMap()
                .get(block_hash)
                .getBlock(jelectrum.getNetworkParameters());

        JSONObject result = Util.getMerkleTreeForTransaction(blk.getTransactions(), tx_hash);
        result.put("block_height", height);

        reply.put("result", result);

        sendMessage(reply);
      } else if (method.equals("blockchain.block.get_chunk")) {
        JSONObject reply = new JSONObject();
        reply.put("id", id);
        JSONArray arr = msg.getJSONArray("params");
        int index = arr.getInt(0);

        reply.put("result", jelectrum.getHeaderChunkAgent().getChunk(index));

        sendMessage(reply);
      } else {
        jelectrum.getEventLog().log(connection_id + " - Unknown electrum method: " + method);
        System.out.println("Unknown method - " + method);
        JSONObject reply = new JSONObject();
        reply.put("id", id);
        reply.put("error", "unknown method - " + method);
        sendMessage(reply);
      }
    } catch (Throwable t) {
      JSONObject reply = new JSONObject();
      reply.put("id", id);
      reply.put("error", "Exception: " + t);
      sendMessage(reply);
      jelectrum.getEventLog().log(connection_id + " - error: " + t);
      jelectrum.getEventLog().log(t);
      // t.printStackTrace();
    }
  }