コード例 #1
0
  @Test
  public void oneTx() throws Exception {
    // Check basic tx serialization.
    Coin v1 = COIN;
    Transaction t1 = createFakeTx(params, v1, myAddress);
    t1.getConfidence().markBroadcastBy(new PeerAddress(InetAddress.getByName("1.2.3.4")));
    t1.getConfidence().markBroadcastBy(new PeerAddress(InetAddress.getByName("5.6.7.8")));
    t1.getConfidence().setSource(TransactionConfidence.Source.NETWORK);
    myWallet.receivePending(t1, null);
    Wallet wallet1 = roundTrip(myWallet);
    assertEquals(1, wallet1.getTransactions(true).size());
    assertEquals(v1, wallet1.getBalance(Wallet.BalanceType.ESTIMATED));
    Transaction t1copy = wallet1.getTransaction(t1.getHash());
    assertArrayEquals(t1.bitcoinSerialize(), t1copy.bitcoinSerialize());
    assertEquals(2, t1copy.getConfidence().numBroadcastPeers());
    assertEquals(TransactionConfidence.Source.NETWORK, t1copy.getConfidence().getSource());

    Protos.Wallet walletProto = new WalletProtobufSerializer().walletToProto(myWallet);
    assertEquals(Protos.Key.Type.ORIGINAL, walletProto.getKey(0).getType());
    assertEquals(0, walletProto.getExtensionCount());
    assertEquals(1, walletProto.getTransactionCount());
    assertEquals(6, walletProto.getKeyCount());

    Protos.Transaction t1p = walletProto.getTransaction(0);
    assertEquals(0, t1p.getBlockHashCount());
    assertArrayEquals(t1.getHash().getBytes(), t1p.getHash().toByteArray());
    assertEquals(Protos.Transaction.Pool.PENDING, t1p.getPool());
    assertFalse(t1p.hasLockTime());
    assertFalse(t1p.getTransactionInput(0).hasSequence());
    assertArrayEquals(
        t1.getInputs().get(0).getOutpoint().getHash().getBytes(),
        t1p.getTransactionInput(0).getTransactionOutPointHash().toByteArray());
    assertEquals(0, t1p.getTransactionInput(0).getTransactionOutPointIndex());
    assertEquals(t1p.getTransactionOutput(0).getValue(), v1.value);
  }
コード例 #2
0
  @Before
  public void setUp() throws Exception {
    unitTestParams = UnitTestParams.get();
    wallet = new Wallet(unitTestParams);
    wallet.addKey(new ECKey());

    resetBlockStore();

    Transaction tx1 =
        createFakeTx(
            unitTestParams,
            Utils.toNanoCoins(2, 0),
            wallet.getKeys().get(0).toAddress(unitTestParams));

    // add a second input so can test granularity of byte cache.
    Transaction prevTx = new Transaction(unitTestParams);
    TransactionOutput prevOut =
        new TransactionOutput(
            unitTestParams,
            prevTx,
            Utils.toNanoCoins(1, 0),
            wallet.getKeys().get(0).toAddress(unitTestParams));
    prevTx.addOutput(prevOut);
    // Connect it.
    tx1.addInput(prevOut);

    Transaction tx2 =
        createFakeTx(
            unitTestParams, Utils.toNanoCoins(1, 0), new ECKey().toAddress(unitTestParams));

    Block b1 = createFakeBlock(blockStore, tx1, tx2).block;

    BitcoinSerializer bs = new BitcoinSerializer(unitTestParams);

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bs.serialize(tx1, bos);
    tx1BytesWithHeader = bos.toByteArray();
    tx1Bytes = tx1.bitcoinSerialize();

    bos.reset();
    bs.serialize(tx2, bos);
    tx2BytesWithHeader = bos.toByteArray();
    tx2Bytes = tx2.bitcoinSerialize();

    bos.reset();
    bs.serialize(b1, bos);
    b1BytesWithHeader = bos.toByteArray();
    b1Bytes = b1.bitcoinSerialize();
  }
コード例 #3
0
 private static void sendTransactionsToListener(
     StoredBlock block,
     NewBlockType blockType,
     BlockChainListener listener,
     int relativityOffset,
     List<Transaction> transactions,
     boolean clone,
     Set<Sha256Hash> falsePositives)
     throws VerificationException {
   for (Transaction tx : transactions) {
     try {
       if (listener.isTransactionRelevant(tx)) {
         falsePositives.remove(tx.getHash());
         if (clone) tx = new Transaction(tx.params, tx.bitcoinSerialize());
         listener.receiveFromBlock(tx, block, blockType, relativityOffset++);
       }
     } catch (ScriptException e) {
       // We don't want scripts we don't understand to break the block chain so just note that this
       // tx was
       // not scanned here and continue.
       log.warn("Failed to parse a script: " + e.toString());
     } catch (ProtocolException e) {
       // Failed to duplicate tx, should never happen.
       throw new RuntimeException(e);
     }
   }
 }
コード例 #4
0
ファイル: MemoryPoolTest.java プロジェクト: njlr/Mixer
  @Before
  public void setup() throws Exception {
    BriefLogFormatter.init();
    tx1 = TestUtils.createFakeTx(params, Utils.toNanoCoins(1, 0), new ECKey().toAddress(params));
    tx2 = new Transaction(params, tx1.bitcoinSerialize());

    address1 = new PeerAddress(InetAddress.getByAddress(new byte[] {127, 0, 0, 1}));
    address2 = new PeerAddress(InetAddress.getByAddress(new byte[] {127, 0, 0, 2}));
    address3 = new PeerAddress(InetAddress.getByAddress(new byte[] {127, 0, 0, 3}));
  }
コード例 #5
0
ファイル: BlockTest.java プロジェクト: ricky000/bitcoinj
 @Test
 public void testUpdateLength() {
   NetworkParameters params = UnitTestParams.get();
   Block block =
       params
           .getGenesisBlock()
           .createNextBlockWithCoinbase(
               Block.BLOCK_VERSION_GENESIS, new ECKey().getPubKey(), Block.BLOCK_HEIGHT_GENESIS);
   assertEquals(block.bitcoinSerialize().length, block.length);
   final int origBlockLen = block.length;
   Transaction tx = new Transaction(params);
   // this is broken until the transaction has > 1 input + output (which is required anyway...)
   // assertTrue(tx.length == tx.bitcoinSerialize().length && tx.length == 8);
   byte[] outputScript = new byte[10];
   Arrays.fill(outputScript, (byte) ScriptOpCodes.OP_FALSE);
   tx.addOutput(new TransactionOutput(params, null, Coin.SATOSHI, outputScript));
   tx.addInput(
       new TransactionInput(
           params,
           null,
           new byte[] {(byte) ScriptOpCodes.OP_FALSE},
           new TransactionOutPoint(params, 0, Sha256Hash.of(new byte[] {1}))));
   int origTxLength = 8 + 2 + 8 + 1 + 10 + 40 + 1 + 1;
   assertEquals(tx.bitcoinSerialize().length, tx.length);
   assertEquals(origTxLength, tx.length);
   block.addTransaction(tx);
   assertEquals(block.bitcoinSerialize().length, block.length);
   assertEquals(origBlockLen + tx.length, block.length);
   block
       .getTransactions()
       .get(1)
       .getInputs()
       .get(0)
       .setScriptBytes(new byte[] {(byte) ScriptOpCodes.OP_FALSE, (byte) ScriptOpCodes.OP_FALSE});
   assertEquals(block.length, origBlockLen + tx.length);
   assertEquals(tx.length, origTxLength + 1);
   block.getTransactions().get(1).getInputs().get(0).setScriptBytes(new byte[] {});
   assertEquals(block.length, block.bitcoinSerialize().length);
   assertEquals(block.length, origBlockLen + tx.length);
   assertEquals(tx.length, origTxLength - 1);
   block
       .getTransactions()
       .get(1)
       .addInput(
           new TransactionInput(
               params,
               null,
               new byte[] {(byte) ScriptOpCodes.OP_FALSE},
               new TransactionOutPoint(params, 0, Sha256Hash.of(new byte[] {1}))));
   assertEquals(block.length, origBlockLen + tx.length);
   assertEquals(tx.length, origTxLength + 41); // - 1 + 40 + 1 + 1
 }
コード例 #6
0
ファイル: PaymentSession.java プロジェクト: pavel4n/isracoinj
 /**
  * Generates a Payment message based on the information in the PaymentRequest. Provide
  * transactions built by the wallet. If the PaymentRequest did not specify a payment_url, returns
  * null.
  *
  * @param txns list of transactions to be included with the Payment message.
  * @param refundAddr will be used by the merchant to send money back if there was a problem.
  * @param memo is a message to include in the payment message sent to the merchant.
  */
 public @Nullable Protos.Payment getPayment(
     List<Transaction> txns, @Nullable Address refundAddr, @Nullable String memo)
     throws IOException {
   if (!paymentDetails.hasPaymentUrl()) return null;
   Protos.Payment.Builder payment = Protos.Payment.newBuilder();
   if (paymentDetails.hasMerchantData()) payment.setMerchantData(paymentDetails.getMerchantData());
   if (refundAddr != null) {
     Protos.Output.Builder refundOutput = Protos.Output.newBuilder();
     refundOutput.setAmount(totalValue.longValue());
     refundOutput.setScript(
         ByteString.copyFrom(ScriptBuilder.createOutputScript(refundAddr).getProgram()));
     payment.addRefundTo(refundOutput);
   }
   if (memo != null) {
     payment.setMemo(memo);
   }
   for (Transaction txn : txns) {
     txn.verify();
     ByteArrayOutputStream o = new ByteArrayOutputStream();
     txn.bitcoinSerialize(o);
     payment.addTransactions(ByteString.copyFrom(o.toByteArray()));
   }
   return payment.build();
 }
コード例 #7
0
  /**
   * This is required for signatures which use a sigHashType which cannot be represented using
   * SigHash and anyoneCanPay See transaction
   * c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73, which has sigHashType 0
   */
  public static synchronized byte[] serializeForSignature(
      Transaction spendingTx, int inputIndex, byte[] connectedScript, byte sigHashType) {
    NetworkParameters params = TestNet3Params.get();
    // The SIGHASH flags are used in the design of contracts, please see this page for a further
    // understanding of
    // the purposes of the code in this method:
    //
    //   https://en.bitcoin.it/wiki/Contracts

    try {

      Transaction tx = new Transaction(params, spendingTx.bitcoinSerialize());
      // Store all the input scripts and clear them in preparation for signing. If we're signing a
      // fresh
      // transaction that step isn't very helpful, but it doesn't add much cost relative to the
      // actual
      // EC math so we'll do it anyway.
      //
      // Also store the input sequence numbers in case we are clearing them with SigHash.NONE/SINGLE

      byte[][] inputScripts = new byte[tx.getInputs().size()][];
      long[] inputSequenceNumbers = new long[tx.getInputs().size()];
      for (int i = 0; i < tx.getInputs().size(); i++) {
        inputScripts[i] = tx.getInputs().get(i).getScriptBytes();
        inputSequenceNumbers[i] = tx.getInputs().get(i).getSequenceNumber();
        tx.getInput(i).setScriptSig(new Script(new byte[0]));
      }

      // This step has no purpose beyond being synchronized with the reference clients bugs.
      // OP_CODESEPARATOR
      // is a legacy holdover from a previous, broken design of executing scripts that shipped in
      // Bitcoin 0.1.
      // It was seriously flawed and would have let anyone take anyone elses money. Later versions
      // switched to
      // the design we use today where scripts are executed independently but share a stack. This
      // left the
      // OP_CODESEPARATOR instruction having no purpose as it was only meant to be used internally,
      // not actually
      // ever put into scripts. Deleting OP_CODESEPARATOR is a step that should never be required
      // but if we don't
      // do it, we could split off the main chain.

      connectedScript =
          Script.removeAllInstancesOfOp(connectedScript, ScriptOpCodes.OP_CODESEPARATOR);
      // Set the input to the script of its output. Satoshi does this but the step has no obvious
      // purpose as
      // the signature covers the hash of the prevout transaction which obviously includes the
      // output script
      // already. Perhaps it felt safer to him in some way, or is another leftover from how the code
      // was written.
      TransactionInput input = tx.getInputs().get(inputIndex);
      input.setScriptSig(new Script(connectedScript));
      List<TransactionOutput> outputs = tx.getOutputs();

      if ((sigHashType & 0x1f) == (Transaction.SigHash.NONE.ordinal() + 1)) {
        // SIGHASH_NONE means no outputs are signed at all - the signature is effectively for a
        // "blank cheque".
        // this.outputs = new ArrayList<TransactionOutput>(0);
        tx.clearOutputs();
        // The signature isn't broken by new versions of the transaction issued by other parties.
        for (int i = 0; i < tx.getInputs().size(); i++)
          if (i != inputIndex) tx.getInputs().get(i).setSequenceNumber(0);
      } else if ((sigHashType & 0x1f) == (Transaction.SigHash.SINGLE.ordinal() + 1)) {
        // SIGHASH_SINGLE means only sign the output at the same index as the input (ie, my output).
        if (inputIndex >= tx.getOutputs().size()) {
          // The input index is beyond the number of outputs, it's a buggy signature made by a
          // broken
          // Bitcoin implementation. The reference client also contains a bug in handling this case:
          // any transaction output that is signed in this case will result in both the signed
          // output
          // and any future outputs to this public key being steal-able by anyone who has
          // the resulting signature and the public key (both of which are part of the signed tx
          // input).
          // Put the transaction back to how we found it.
          //
          // TODO: Only allow this to happen if we are checking a signature, not signing a
          // transactions
          for (int i = 0; i < tx.getInputs().size(); i++) {
            // tx.getInputs().get(i).setScriptSig(inputScripts[i]);
            /*                        tx.getInputs().get(i).setScriptSig(ScriptBuilder.createMultiSigInputScriptBytes(
            Arrays.asList(inputScripts[i])));*/
            tx.getInput(i).setScriptSig(new Script(inputScripts[i]));
            tx.getInputs().get(i).setSequenceNumber(inputSequenceNumbers[i]);
          }
          // this.outputs = outputs;

          // Satoshis bug is that SignatureHash was supposed to return a hash and on this codepath
          // it
          // actually returns the constant "1" to indicate an error, which is never checked for.
          // Oops.
          return Utils.HEX.decode(
              "0100000000000000000000000000000000000000000000000000000000000000");
        }

        // In SIGHASH_SINGLE the outputs after the matching input index are deleted, and the outputs
        // before
        // that position are "nulled out". Unintuitively, the value in a "null" transaction is set
        // to -1.
        /*                this.outputs = new ArrayList<TransactionOutput>(this.outputs.subList(0, inputIndex + 1));
        for (int i = 0; i < inputIndex; i++)
            this.outputs.set(i, new TransactionOutput(params, this, Coin.NEGATIVE_SATOSHI, new byte[] {}));
        // The signature isn't broken by new versions of the transaction issued by other parties.
        for (int i = 0; i < inputs.size(); i++)
            if (i != inputIndex)
                inputs.get(i).setSequenceNumber(0);*/
        // In SIGHASH_SINGLE the outputs after the matching input index are deleted, and the outputs
        // before
        // that position are "nulled out". Unintuitively, the value in a "null" transaction is set
        // to -1.
        // tx.outputs = new ArrayList<TransactionOutput>(tx.getOutputs().subList(0, inputIndex +
        // 1));
        tx.clearOutputs();
        for (int i = 0; i <= inputIndex; i++)
          if (i == inputIndex) {
            // need to make sure the output at inputIndex stays the same
            tx.addOutput(spendingTx.getOutput(inputIndex));
          } else {
            // this.outputs.set(i, new TransactionOutput(params, this, Coin.NEGATIVE_SATOSHI, new
            // byte[] {}));
            tx.addOutput(new TransactionOutput(params, tx, Coin.NEGATIVE_SATOSHI, new byte[] {}));
          }

        // The signature isn't broken by new versions of the transaction issued by other parties.
        for (int i = 0; i < tx.getInputs().size(); i++)
          if (i != inputIndex) tx.getInputs().get(i).setSequenceNumber(0);
      }

      List<TransactionInput> inputs = tx.getInputs();
      if ((sigHashType & (byte) 0x80) == 0x80) {
        // SIGHASH_ANYONECANPAY means the signature in the input is not broken by
        // changes/additions/removals
        // of other inputs. For example, this is useful for building assurance contracts.
        tx.clearInputs();
        tx.getInputs().add(input);
      }

      ByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(256);
      tx.bitcoinSerialize(bos);
      // We also have to write a hash type (sigHashType is actually an unsigned char)
      uint32ToByteStreamLE(0x000000ff & sigHashType, bos);
      // Note that this is NOT reversed to ensure it will be signed correctly. If it were to be
      // printed out
      // however then we would expect that it is IS reversed.
      byte[] txSignatureBytes = bos.toByteArray();
      bos.close();

      // Put the transaction back to how we found it.
      // tx.inputs = inputs;
      tx.clearInputs();
      for (int i = 0; i < inputs.size(); i++) {
        tx.addInput(inputs.get(i));
      }
      for (int i = 0; i < inputs.size(); i++) {
        inputs.get(i).setScriptSig(new Script(inputScripts[i]));
        inputs.get(i).setSequenceNumber(inputSequenceNumbers[i]);
      }
      // this.outputs = outputs;
      tx.clearOutputs();
      for (int i = 0; i < outputs.size(); i++) {
        tx.addOutput(outputs.get(i));
      }
      return txSignatureBytes;
    } catch (IOException e) {
      throw new RuntimeException(e); // Cannot happen.
    }
  }