/**
 * Copyright 2012 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.bitcoinj.core;

import org.bitcoinj.core.AbstractBlockChain.NewBlockType;
import org.bitcoinj.core.Wallet.BalanceType;
import org.bitcoinj.params.MainNetParams;
import org.junit.Before;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.EnumSet;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

/**
 * Test that an example mainnet coinbase transactions can be added to a wallet ok.
 */
public class CoinbaseBlockTest {
    static final NetworkParameters params = MainNetParams.get();

    // The address for this private key is 1GqtGtn4fctXuKxsVzRPSLmYWN1YioLi9y.
    private static final String MINING_PRIVATE_KEY = "5JDxPrBRghF1EvSBjDigywqfmAjpHPmTJxYtQTYJxJRHLLQA4mG";

    private static final int BLOCK_OF_INTEREST = 169482;
    private static final int BLOCK_LENGTH_AS_HEX = 37357;
    private static final long BLOCK_NONCE = 3973947400L;
    private static final Coin BALANCE_AFTER_BLOCK = Coin.valueOf(22223642);

    @Before
    public void setUp() throws Exception {
        Context context = new Context(params);
    }

    @Test
    public void testReceiveCoinbaseTransaction() throws Exception {
        // Block 169482 (hash 0000000000000756935f1ee9d5987857b604046f846d3df56d024cdb5f368665)
        // contains coinbase transactions that are mining pool shares.
        // The private key MINERS_KEY is used to check transactions are received by a wallet correctly.

        byte[] blockAsBytes = getBytes(getClass().getResourceAsStream("block169482.dat"));

        // Create block 169482.
        Block block = params.getDefaultSerializer().makeBlock(blockAsBytes);

        // Check block.
        assertNotNull(block);
        block.verify(169482, EnumSet.noneOf(Block.VerifyFlag.class));
        assertEquals(BLOCK_NONCE, block.getNonce());

        StoredBlock storedBlock = new StoredBlock(block, BigInteger.ONE, BLOCK_OF_INTEREST); // Nonsense work - not used in test.

        // Create a wallet contain the miner's key that receives a spend from a coinbase.
        ECKey miningKey = DumpedPrivateKey.fromBase58(params, MINING_PRIVATE_KEY).getKey();
        assertNotNull(miningKey);
        Context context = new Context(params);
        Wallet wallet = new Wallet(context);
        wallet.importKey(miningKey);

        // Initial balance should be zero by construction.
        assertEquals(Coin.ZERO, wallet.getBalance());

        // Give the wallet the first transaction in the block - this is the coinbase tx.
        List<Transaction> transactions = block.getTransactions();
        assertNotNull(transactions);
        wallet.receiveFromBlock(transactions.get(0), storedBlock, NewBlockType.BEST_CHAIN, 0);

        // Coinbase transaction should have been received successfully but be unavailable to spend (too young).
        assertEquals(BALANCE_AFTER_BLOCK, wallet.getBalance(BalanceType.ESTIMATED));
        assertEquals(Coin.ZERO, wallet.getBalance(BalanceType.AVAILABLE));
    }

    /**
     * Returns the contents of the InputStream as a byte array.
     */
    private byte[] getBytes(InputStream inputStream) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();

        int numberRead;
        byte[] data = new byte[BLOCK_LENGTH_AS_HEX];

        while ((numberRead = inputStream.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, numberRead);
        }

        buffer.flush();

        return buffer.toByteArray();
    }
}

@@ -27,16 +27,53 @@
 le Inc.%0A
+ * Copyright 2015 Andreas Schildbach%0A
  *%0A * Li
@@ -859,94 +859,42 @@
 ort 
-java.io.ByteArrayOutputStream;%0Aimport java.io.IOException;%0Aimport java.io.Input
+com.google.common.io.Byte
 Stream
-;
+s;%0A
 %0Aimp
@@ -1500,66 +1500,8 @@
 82;%0A
-    private static final int BLOCK_LENGTH_AS_HEX = 37357;%0A
     
@@ -2101,198 +2101,142 @@
     
-byte%5B%5D blockAsBytes = getBytes(getClass().getResourceAsStream(%22block169482.dat%22));%0A%0A        // Create block 169482.%0A        Block block = params.getDefaultSerializer().makeBlock(blockAsBytes
+Block block169482 = params.getDefaultSerializer().makeBlock(ByteStreams.toByteArray(getClass().getResourceAsStream(%22block169482.dat%22))
 );%0A%0A
@@ -2286,16 +2286,22 @@
 ll(block
+169482
 );%0A     
@@ -2308,16 +2308,22 @@
    block
+169482
 .verify(
@@ -2406,24 +2406,30 @@
 NONCE, block
+169482
 .getNonce())
@@ -2486,16 +2486,22 @@
 ck(block
+169482
 , BigInt
@@ -3163,16 +3163,22 @@
  = block
+169482
 .getTran
@@ -3603,513 +3603,7 @@
    %7D
-%0A%0A    /**%0A     * Returns the contents of the InputStream as a byte array.%0A     */%0A    private byte%5B%5D getBytes(InputStream inputStream) throws IOException %7B%0A        ByteArrayOutputStream buffer = new ByteArrayOutputStream();%0A%0A        int numberRead;%0A        byte%5B%5D data = new byte%5BBLOCK_LENGTH_AS_HEX%5D;%0A%0A        while ((numberRead = inputStream.read(data, 0, data.length)) != -1) %7B%0A            buffer.write(data, 0, numberRead);%0A        %7D%0A%0A        buffer.flush();%0A%0A        return buffer.toByteArray();%0A    %7D
 %0A%7D%0A

Convert some file loading code to use Guava.