/**
   * For each block we are looking for our transactions and clearing them The actual receiver
   * balance is confirmed upon block arrival
   */
  public void onBlock(Block block, List<TransactionReceipt> receipts) {
    int cleared = 0;
    for (Transaction tx : block.getTransactionsList()) {
      ByteArrayWrapper txHash = new ByteArrayWrapper(tx.getHash());
      Transaction ptx = pendingTxs.get(txHash);
      if (ptx != null) {
        logger.info(
            " - Pending transaction cleared 0x"
                + Hex.toHexString(tx.getHash()).substring(0, 8)
                + " in block "
                + block.getShortDescr());

        pendingTxs.remove(txHash);
        cleared++;
      }
    }
    BigInteger receiverBalance = ethereum.getRepository().getBalance(receiverAddress);
    BigInteger receiverBalancePending = pendingState.getRepository().getBalance(receiverAddress);
    logger.info("" + cleared + " transactions cleared in the block " + block.getShortDescr());
    logger.info(
        "Receiver pending/current balance: "
            + receiverBalancePending
            + " / "
            + receiverBalance
            + " ("
            + pendingTxs.size()
            + " pending txs)");
  }
Beispiel #2
0
  @Override
  public boolean equals(Object obj) {

    if (!(obj instanceof Transaction)) return false;
    Transaction tx = (Transaction) obj;

    return tx.hashCode() == this.hashCode();
  }
  @Override
  public Block createForkBlock(Block parent) {
    try {
      List<Transaction> txes = new ArrayList<>();
      Map<ByteArrayWrapper, Long> nonces = new HashMap<>();
      Repository repoSnapshot =
          getBlockchain().getRepository().getSnapshotTo(parent.getStateRoot());
      for (PendingTx tx : submittedTxes) {
        ByteArrayWrapper senderW = new ByteArrayWrapper(tx.sender.getAddress());
        Long nonce = nonces.get(senderW);
        if (nonce == null) {
          BigInteger bcNonce = repoSnapshot.getNonce(tx.sender.getAddress());
          nonce = bcNonce.longValue();
        }
        nonces.put(senderW, nonce + 1);

        byte[] toAddress =
            tx.targetContract != null ? tx.targetContract.getAddress() : tx.toAddress;

        Transaction transaction =
            new Transaction(
                ByteUtil.longToBytesNoLeadZeroes(nonce),
                ByteUtil.longToBytesNoLeadZeroes(gasPrice),
                ByteUtil.longToBytesNoLeadZeroes(gasLimit),
                toAddress,
                ByteUtil.bigIntegerToBytes(tx.value),
                tx.data);
        transaction.sign(tx.sender.getPrivKeyBytes());
        if (tx.createdContract != null) {
          tx.createdContract.setAddress(transaction.getContractAddress());
        }
        txes.add(transaction);
      }
      Block b = getBlockchain().createNewBlock(parent, txes, Collections.EMPTY_LIST);
      Ethash.getForBlock(b.getNumber()).mineLight(b).get();
      ImportResult importResult = getBlockchain().tryToConnect(b);
      if (importResult != ImportResult.IMPORTED_BEST
          && importResult != ImportResult.IMPORTED_NOT_BEST) {
        throw new RuntimeException(
            "Invalid block import result " + importResult + " for block " + b);
      }
      submittedTxes.clear();
      return b;
    } catch (InterruptedException | ExecutionException e) {
      throw new RuntimeException(e);
    }
  }
  /**
   * The PendingState is updated with a new pending transactions. Prints the current receiver
   * balance (based on blocks) and the pending balance which should immediately reflect receiver
   * balance change
   */
  void onPendingTransactionReceived(Transaction tx) {
    logger.info("onPendingTransactionReceived: " + tx);
    if (Arrays.equals(tx.getSender(), senderAddress)) {
      BigInteger receiverBalance = ethereum.getRepository().getBalance(receiverAddress);
      BigInteger receiverBalancePending = pendingState.getRepository().getBalance(receiverAddress);
      logger.info(" + New pending transaction 0x" + Hex.toHexString(tx.getHash()).substring(0, 8));

      pendingTxs.put(new ByteArrayWrapper(tx.getHash()), tx);

      logger.info(
          "Receiver pending/current balance: "
              + receiverBalancePending
              + " / "
              + receiverBalance
              + " ("
              + pendingTxs.size()
              + " pending txs)");
    }
  }
    @Override
    public Object[] callConstFunction(Block callBlock, String functionName, Object... args) {

      Transaction tx =
          CallTransaction.createCallTransaction(
              0,
              0,
              100000000000000L,
              Hex.toHexString(getAddress()),
              0,
              contract.getByName(functionName),
              args);
      tx.sign(new byte[32]);

      Repository repository =
          getBlockchain().getRepository().getSnapshotTo(callBlock.getStateRoot()).startTracking();

      try {
        org.ethereum.core.TransactionExecutor executor =
            new org.ethereum.core.TransactionExecutor(
                    tx,
                    callBlock.getCoinbase(),
                    repository,
                    getBlockchain().getBlockStore(),
                    getBlockchain().getProgramInvokeFactory(),
                    callBlock)
                .setLocalCall(true);

        executor.init();
        executor.execute();
        executor.go();
        executor.finalization();

        return contract.getByName(functionName).decodeResult(executor.getResult().getHReturn());
      } finally {
        repository.rollback();
      }
    }
  /**
   * Periodically send value transfer transactions and each 5 transactions wait for all sent
   * transactions to be included into blocks
   */
  void sendTransactions() throws InterruptedException {
    // initial sender nonce needs to be retrieved from the repository
    // for further transactions we just do nonce++
    BigInteger nonce = ethereum.getRepository().getNonce(senderAddress);

    int weisToSend = 100;
    int count = 0;
    while (true) {
      if (count < 5) {
        Transaction tx =
            new Transaction(
                ByteUtil.bigIntegerToBytes(nonce),
                ByteUtil.longToBytesNoLeadZeroes(ethereum.getGasPrice()),
                ByteUtil.longToBytesNoLeadZeroes(1_000_000),
                receiverAddress,
                ByteUtil.longToBytesNoLeadZeroes(weisToSend),
                new byte[0]);
        tx.sign(senderPrivateKey);
        logger.info("<=== Sending transaction: " + tx);
        ethereum.submitTransaction(tx);

        nonce = nonce.add(BigInteger.ONE);
        count++;
      } else {
        if (pendingTxs.size() > 0) {
          logger.info(
              "Waiting for transaction clearing. " + pendingTxs.size() + " transactions remain.");
        } else {
          logger.info("All transactions are included to blocks!");
          count = 0;
        }
      }

      Thread.sleep(7000);
    }
  }
  @Override
  public Transaction call() throws Exception {

    try {
      logger.info("call() tx: {}", tx.toString());

      ClientPeer peer = MainData.instance.getActivePeer();

      WalletTransaction walletTransaction =
          WorldManager.instance.getBlockChain().addWalletTransaction(tx);
      peer.sendTransaction(tx);

      while (walletTransaction.getApproved() < 1) {
        sleep(10);
      }

      logger.info("return approved: {}", walletTransaction.getApproved());
    } catch (Throwable th) {
      logger.info("exception caugh: {}", th.getCause());
      WorldManager.instance.getBlockChain().removeWalletTransaction(tx);
    }

    return null;
  }