Program: 85806
Project: 85806
Buggy source:
@Test public void feeSolverAndCoinSelectionTest() throws Exception {
  assertEquals(0,wallet.getTransactions(true).size());
  Address notMyAddr=new ECKey().toAddress(params);
  StoredBlock block=new StoredBlock(makeSolvedTestBlock(blockStore,notMyAddr),BigInteger.ONE,1);
  Transaction tx1=createFakeTx(params,BigInteger.ONE,myAddress);
  wallet.receiveFromBlock(tx1,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  Transaction tx2=createFakeTx(params,BigInteger.ONE,myAddress);
  assertTrue(!tx1.getHash().equals(tx2.getHash()));
  wallet.receiveFromBlock(tx2,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  Transaction tx3=createFakeTx(params,BigInteger.TEN,myAddress);
  wallet.receiveFromBlock(tx3,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  assertNull(wallet.createSend(notMyAddr,BigInteger.ONE));
  SendRequest req=SendRequest.to(notMyAddr,BigInteger.TEN.add(BigInteger.ONE.add(BigInteger.ONE)));
  req.ensureMinRequiredFee=false;
  assertNotNull(wallet.sendCoinsOffline(req));
  assertEquals(BigInteger.ZERO,wallet.getBalance());
  block=new StoredBlock(makeSolvedTestBlock(blockStore,notMyAddr),BigInteger.ONE,1);
  Transaction tx4=createFakeTx(params,Utils.COIN,myAddress);
  wallet.receiveFromBlock(tx4,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  Transaction spend1=wallet.createSend(notMyAddr,Utils.CENT.subtract(BigInteger.ONE));
  assertEquals(2,spend1.getOutputs().size());
  assertEquals(spend1.getOutput(0).getValue().add(spend1.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  Transaction spend2=wallet.createSend(notMyAddr,Utils.CENT);
  assertEquals(2,spend2.getOutputs().size());
  assertEquals(Utils.COIN,spend2.getOutput(0).getValue().add(spend2.getOutput(1).getValue()));
  SendRequest request3=SendRequest.to(notMyAddr,Utils.CENT.subtract(BigInteger.ONE));
  request3.fee=Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE);
  assertTrue(wallet.completeTx(request3));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE),request3.fee);
  Transaction spend3=request3.tx;
  assertEquals(2,spend3.getOutputs().size());
  assertEquals(spend3.getOutput(0).getValue().add(spend3.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE)));
  SendRequest request4=SendRequest.to(notMyAddr,Utils.CENT.subtract(BigInteger.ONE));
  request4.fee=Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(BigInteger.ONE);
  assertTrue(wallet.completeTx(request4));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request4.fee);
  Transaction spend4=request4.tx;
  assertEquals(2,spend4.getOutputs().size());
  assertEquals(spend4.getOutput(0).getValue().add(spend4.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request5=SendRequest.to(notMyAddr,Utils.COIN.subtract(Utils.CENT.subtract(BigInteger.ONE)));
  assertTrue(wallet.completeTx(request5));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request5.fee);
  Transaction spend5=request5.tx;
  assertEquals(2,spend5.getOutputs().size());
  assertEquals(spend5.getOutput(0).getValue().add(spend5.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request6=SendRequest.to(notMyAddr,Utils.COIN.subtract(Utils.CENT));
  assertTrue(wallet.completeTx(request6));
  assertEquals(BigInteger.ZERO,request6.fee);
  Transaction spend6=request6.tx;
  assertEquals(2,spend6.getOutputs().size());
  assertEquals(Utils.COIN,spend6.getOutput(0).getValue().add(spend6.getOutput(1).getValue()));
  SendRequest request7=SendRequest.to(notMyAddr,Utils.COIN.subtract(Utils.CENT.subtract(BigInteger.valueOf(2)).multiply(BigInteger.valueOf(2))));
  request7.tx.addOutput(Utils.CENT.subtract(BigInteger.ONE),notMyAddr);
  assertTrue(wallet.completeTx(request7));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request7.fee);
  Transaction spend7=request7.tx;
  assertEquals(3,spend7.getOutputs().size());
  assertEquals(spend7.getOutput(0).getValue().add(spend7.getOutput(1).getValue()).add(spend7.getOutput(2).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request8=SendRequest.to(notMyAddr,Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  assertTrue(wallet.completeTx(request8));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request8.fee);
  Transaction spend8=request8.tx;
  assertEquals(1,spend8.getOutputs().size());
  assertEquals(spend8.getOutput(0).getValue(),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request9=SendRequest.to(notMyAddr,Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)));
  assertTrue(wallet.completeTx(request9));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT),request9.fee);
  Transaction spend9=request9.tx;
  assertEquals(1,spend9.getOutputs().size());
  assertEquals(spend9.getOutput(0).getValue(),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)));
  SendRequest request10=SendRequest.to(notMyAddr,Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(BigInteger.ONE)));
  assertTrue(wallet.completeTx(request10));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request10.fee);
  Transaction spend10=request10.tx;
  assertEquals(2,spend10.getOutputs().size());
  assertEquals(spend10.getOutput(0).getValue().add(spend10.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request11=SendRequest.to(notMyAddr,Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(BigInteger.valueOf(2))));
  request11.fee=Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE);
  assertTrue(wallet.completeTx(request11));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE),request11.fee);
  Transaction spend11=request11.tx;
  assertEquals(2,spend11.getOutputs().size());
  assertEquals(spend11.getOutput(0).getValue().add(spend11.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE)));
  wallet.commitTx(spend11);
  Transaction tx5=createFakeTx(params,Utils.CENT,myAddress);
  wallet.receiveFromBlock(tx5,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  assertEquals(Utils.CENT,wallet.getBalance());
  for (int i=0; i < 100; i++) {
    block=new StoredBlock(makeSolvedTestBlock(blockStore,notMyAddr),BigInteger.ONE,1);
    wallet.notifyNewBestBlock(block);
  }
  block=new StoredBlock(makeSolvedTestBlock(blockStore,notMyAddr),BigInteger.ONE,1);
  Transaction tx6=createFakeTx(params,Utils.COIN,myAddress);
  wallet.receiveFromBlock(tx6,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  assertTrue(tx5.getOutput(0).isMine(wallet) && tx5.getOutput(0).isAvailableForSpending() && tx5.getConfidence().getDepthInBlocks() == 100);
  assertTrue(tx6.getOutput(0).isMine(wallet) && tx6.getOutput(0).isAvailableForSpending() && tx6.getConfidence().getDepthInBlocks() == 1);
  Transaction spend12=wallet.createSend(notMyAddr,Utils.CENT);
  assertTrue(spend12.getOutputs().size() == 2 && spend12.getOutput(0).getValue().add(spend12.getOutput(1).getValue()).equals(Utils.COIN));
  wallet.notifyNewBestBlock(block);
  assertTrue(tx5.getOutput(0).isMine(wallet) && tx5.getOutput(0).isAvailableForSpending() && tx5.getConfidence().getDepthInBlocks() == 101);
  assertTrue(tx6.getOutput(0).isMine(wallet) && tx6.getOutput(0).isAvailableForSpending() && tx6.getConfidence().getDepthInBlocks() == 1);
  Transaction spend13=wallet.createSend(notMyAddr,Utils.CENT);
  assertTrue(spend13.getOutputs().size() == 1 && spend13.getOutput(0).getValue().equals(Utils.CENT));
  block=new StoredBlock(makeSolvedTestBlock(blockStore,notMyAddr),BigInteger.ONE,1);
  wallet.notifyNewBestBlock(block);
  assertTrue(tx5.getOutput(0).isMine(wallet) && tx5.getOutput(0).isAvailableForSpending() && tx5.getConfidence().getDepthInBlocks() == 102);
  assertTrue(tx6.getOutput(0).isMine(wallet) && tx6.getOutput(0).isAvailableForSpending() && tx6.getConfidence().getDepthInBlocks() == 2);
  Transaction spend14=wallet.createSend(notMyAddr,Utils.CENT);
  assertTrue(spend14.getOutputs().size() == 2 && spend14.getOutput(0).getValue().add(spend14.getOutput(1).getValue()).equals(Utils.COIN));
  SendRequest request15=SendRequest.to(notMyAddr,Utils.CENT);
  for (int i=0; i < 29; i++)   request15.tx.addOutput(Utils.CENT,notMyAddr);
  assertTrue(request15.tx.bitcoinSerialize().length > 1000);
  request15.feePerKb=BigInteger.ONE;
  assertTrue(wallet.completeTx(request15));
  assertEquals(BigInteger.valueOf(2),request15.fee);
  Transaction spend15=request15.tx;
  assertEquals(31,spend15.getOutputs().size());
  BigInteger outValue15=BigInteger.ZERO;
  for (  TransactionOutput out : spend15.getOutputs())   outValue15=outValue15.add(out.getValue());
  assertEquals(Utils.COIN.subtract(BigInteger.valueOf(2)),outValue15);
  SendRequest request16=SendRequest.to(notMyAddr,Utils.CENT);
  request16.feePerKb=BigInteger.ZERO;
  for (int i=0; i < 29; i++)   request16.tx.addOutput(Utils.CENT,notMyAddr);
  assertTrue(request16.tx.bitcoinSerialize().length > 1000);
  assertTrue(wallet.completeTx(request16));
  assertEquals(BigInteger.ZERO,request16.fee);
  Transaction spend16=request16.tx;
  assertEquals(31,spend16.getOutputs().size());
  BigInteger outValue16=BigInteger.ZERO;
  for (  TransactionOutput out : spend16.getOutputs())   outValue16=outValue16.add(out.getValue());
  assertEquals(Utils.COIN,outValue16);
  SendRequest request17=SendRequest.to(notMyAddr,Utils.CENT);
  for (int i=0; i < 22; i++)   request17.tx.addOutput(Utils.CENT,notMyAddr);
  request17.tx.addOutput(new TransactionOutput(params,request17.tx,Utils.CENT,new byte[15]));
  request17.feePerKb=BigInteger.ONE;
  assertTrue(wallet.completeTx(request17));
  assertEquals(BigInteger.ONE,request17.fee);
  assertEquals(1,request17.tx.getInputs().size());
  int theoreticalMaxLength17=request17.tx.bitcoinSerialize().length + myKey.getPubKey().length + 75;
  for (  TransactionInput in : request17.tx.getInputs())   theoreticalMaxLength17-=in.getScriptBytes().length;
  assertEquals(999,theoreticalMaxLength17);
  Transaction spend17=request17.tx;
{
    final int length=spend17.bitcoinSerialize().length;
    assertTrue(Integer.toString(length),length >= 997 && length <= 999);
  }
  assertEquals(25,spend17.getOutputs().size());
  BigInteger outValue17=BigInteger.ZERO;
  for (  TransactionOutput out : spend17.getOutputs())   outValue17=outValue17.add(out.getValue());
  assertEquals(Utils.COIN.subtract(BigInteger.ONE),outValue17);
  SendRequest request18=SendRequest.to(notMyAddr,Utils.CENT);
  for (int i=0; i < 22; i++)   request18.tx.addOutput(Utils.CENT,notMyAddr);
  request18.tx.addOutput(new TransactionOutput(params,request18.tx,Utils.CENT,new byte[17]));
  request18.feePerKb=BigInteger.ONE;
  assertTrue(wallet.completeTx(request18));
  assertEquals(BigInteger.valueOf(2),request18.fee);
  assertEquals(1,request18.tx.getInputs().size());
  Transaction spend18=request18.tx;
  int theoreticalMaxLength18=spend18.bitcoinSerialize().length + myKey.getPubKey().length + 75;
  for (  TransactionInput in : spend18.getInputs())   theoreticalMaxLength18-=in.getScriptBytes().length;
  assertEquals(1001,theoreticalMaxLength18);
  assertTrue(spend18.bitcoinSerialize().length >= 998);
  assertTrue(spend18.bitcoinSerialize().length <= 1001);
  assertEquals(25,spend18.getOutputs().size());
  BigInteger outValue18=BigInteger.ZERO;
  for (  TransactionOutput out : spend18.getOutputs())   outValue18=outValue18.add(out.getValue());
  assertEquals(outValue18,Utils.COIN.subtract(BigInteger.valueOf(2)));
  assertEquals(wallet.getBalance(),Utils.CENT.add(Utils.COIN));
  SendRequest request19=SendRequest.to(notMyAddr,Utils.CENT);
  request19.feePerKb=BigInteger.ZERO;
  for (int i=0; i < 99; i++)   request19.tx.addOutput(Utils.CENT,notMyAddr);
  assertTrue(wallet.completeTx(request19));
  assertEquals(BigInteger.ZERO,request19.fee);
  assertEquals(1,request19.tx.getInputs().size());
  assertEquals(100,request19.tx.getOutputs().size());
  request19.tx.clearInputs();
  request19=SendRequest.forTx(request19.tx);
  request19.feePerKb=BigInteger.ONE;
  assertTrue(wallet.completeTx(request19));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request19.fee);
  assertEquals(2,request19.tx.getInputs().size());
  BigInteger outValue19=BigInteger.ZERO;
  for (  TransactionOutput out : request19.tx.getOutputs())   outValue19=outValue19.add(out.getValue());
  assertEquals(request19.tx.getOutput(request19.tx.getOutputs().size() - 1).getValue(),Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  assertEquals(outValue19,Utils.COIN.add(Utils.CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request20=SendRequest.to(notMyAddr,Utils.CENT);
  request20.feePerKb=BigInteger.ZERO;
  for (int i=0; i < 99; i++)   request20.tx.addOutput(Utils.CENT,notMyAddr);
  assertTrue(wallet.completeTx(request20));
  assertEquals(BigInteger.ZERO,request20.fee);
  assertEquals(1,request20.tx.getInputs().size());
  assertEquals(100,request20.tx.getOutputs().size());
  request20.tx.clearInputs();
  request20=SendRequest.forTx(request20.tx);
  request20.feePerKb=Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
  assertTrue(wallet.completeTx(request20));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(4)),request20.fee);
  assertEquals(2,request20.tx.getInputs().size());
  BigInteger outValue20=BigInteger.ZERO;
  for (  TransactionOutput out : request20.tx.getOutputs())   outValue20=outValue20.add(out.getValue());
  assertEquals(outValue20,Utils.COIN.add(Utils.CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(4))));
  SendRequest request21=SendRequest.to(notMyAddr,Utils.CENT);
  request21.feePerKb=BigInteger.ZERO;
  for (int i=0; i < 99; i++)   request21.tx.addOutput(Utils.CENT,notMyAddr);
  request21.tx.addOutput(Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE),notMyAddr);
  assertTrue(wallet.completeTx(request21));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request21.fee);
  assertEquals(2,request21.tx.getInputs().size());
  BigInteger outValue21=BigInteger.ZERO;
  for (  TransactionOutput out : request21.tx.getOutputs())   outValue21=outValue21.add(out.getValue());
  assertEquals(outValue21,Utils.COIN.add(Utils.CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request25=SendRequest.to(notMyAddr,Utils.CENT);
  request25.feePerKb=BigInteger.ZERO;
  for (int i=0; i < 70; i++)   request25.tx.addOutput(Utils.CENT,notMyAddr);
  assertTrue(wallet.completeTx(request25));
  assertEquals(BigInteger.ZERO,request25.fee);
  assertEquals(1,request25.tx.getInputs().size());
  assertEquals(72,request25.tx.getOutputs().size());
  System.out.println(request25.tx.bitcoinSerialize().length);
  request25.tx.clearInputs();
  request25=SendRequest.forTx(request25.tx);
  request25.feePerKb=Utils.CENT.divide(BigInteger.valueOf(3));
  request25.ensureMinRequiredFee=false;
  assertTrue(wallet.completeTx(request25));
  assertEquals(Utils.CENT.subtract(BigInteger.ONE),request25.fee);
  assertEquals(2,request25.tx.getInputs().size());
  BigInteger outValue25=BigInteger.ZERO;
  for (  TransactionOutput out : request25.tx.getOutputs())   outValue25=outValue25.add(out.getValue());
  assertEquals(BigInteger.ONE,request25.tx.getOutput(request25.tx.getOutputs().size() - 1).getValue());
  assertEquals(outValue25,Utils.COIN.add(BigInteger.ONE));
  Transaction spendTx5=new Transaction(params);
  spendTx5.addOutput(Utils.CENT,notMyAddr);
  spendTx5.addInput(tx5.getOutput(0));
  spendTx5.signInputs(SigHash.ALL,wallet);
  wallet.receiveFromBlock(spendTx5,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  assertEquals(Utils.COIN,wallet.getBalance());
  SendRequest request26=SendRequest.to(notMyAddr,Utils.CENT);
  for (int i=0; i < 98; i++)   request26.tx.addOutput(Utils.CENT,notMyAddr);
  request26.tx.addOutput(Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)),notMyAddr);
  assertTrue(request26.tx.bitcoinSerialize().length > 1000);
  request26.feePerKb=BigInteger.ONE;
  assertTrue(wallet.completeTx(request26));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT),request26.fee);
  Transaction spend26=request26.tx;
  assertEquals(100,spend26.getOutputs().size());
  BigInteger outValue26=BigInteger.ZERO;
  for (  TransactionOutput out : spend26.getOutputs())   outValue26=outValue26.add(out.getValue());
  assertEquals(outValue26,Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)));
}

Fixed version (ground truth):
@Test public void feeSolverAndCoinSelectionTest() throws Exception {
  assertEquals(0,wallet.getTransactions(true).size());
  Address notMyAddr=new ECKey().toAddress(params);
  StoredBlock block=new StoredBlock(makeSolvedTestBlock(blockStore,notMyAddr),BigInteger.ONE,1);
  Transaction tx1=createFakeTx(params,BigInteger.ONE,myAddress);
  wallet.receiveFromBlock(tx1,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  Transaction tx2=createFakeTx(params,BigInteger.ONE,myAddress);
  assertTrue(!tx1.getHash().equals(tx2.getHash()));
  wallet.receiveFromBlock(tx2,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  Transaction tx3=createFakeTx(params,BigInteger.TEN,myAddress);
  wallet.receiveFromBlock(tx3,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  assertNull(wallet.createSend(notMyAddr,BigInteger.ONE));
  SendRequest req=SendRequest.to(notMyAddr,BigInteger.TEN.add(BigInteger.ONE.add(BigInteger.ONE)));
  req.ensureMinRequiredFee=false;
  assertNotNull(wallet.sendCoinsOffline(req));
  assertEquals(BigInteger.ZERO,wallet.getBalance());
  block=new StoredBlock(makeSolvedTestBlock(blockStore,notMyAddr),BigInteger.ONE,1);
  Transaction tx4=createFakeTx(params,Utils.COIN,myAddress);
  wallet.receiveFromBlock(tx4,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  Transaction spend1=wallet.createSend(notMyAddr,Utils.CENT.subtract(BigInteger.ONE));
  assertEquals(2,spend1.getOutputs().size());
  assertEquals(spend1.getOutput(0).getValue().add(spend1.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  Transaction spend2=wallet.createSend(notMyAddr,Utils.CENT);
  assertEquals(2,spend2.getOutputs().size());
  assertEquals(Utils.COIN,spend2.getOutput(0).getValue().add(spend2.getOutput(1).getValue()));
  SendRequest request3=SendRequest.to(notMyAddr,Utils.CENT.subtract(BigInteger.ONE));
  request3.fee=Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE);
  assertTrue(wallet.completeTx(request3));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE),request3.fee);
  Transaction spend3=request3.tx;
  assertEquals(2,spend3.getOutputs().size());
  assertEquals(spend3.getOutput(0).getValue().add(spend3.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE)));
  SendRequest request4=SendRequest.to(notMyAddr,Utils.CENT.subtract(BigInteger.ONE));
  request4.fee=Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(BigInteger.ONE);
  assertTrue(wallet.completeTx(request4));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request4.fee);
  Transaction spend4=request4.tx;
  assertEquals(2,spend4.getOutputs().size());
  assertEquals(spend4.getOutput(0).getValue().add(spend4.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request5=SendRequest.to(notMyAddr,Utils.COIN.subtract(Utils.CENT.subtract(BigInteger.ONE)));
  assertTrue(wallet.completeTx(request5));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request5.fee);
  Transaction spend5=request5.tx;
  assertEquals(2,spend5.getOutputs().size());
  assertEquals(spend5.getOutput(0).getValue().add(spend5.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request6=SendRequest.to(notMyAddr,Utils.COIN.subtract(Utils.CENT));
  assertTrue(wallet.completeTx(request6));
  assertEquals(BigInteger.ZERO,request6.fee);
  Transaction spend6=request6.tx;
  assertEquals(2,spend6.getOutputs().size());
  assertEquals(Utils.COIN,spend6.getOutput(0).getValue().add(spend6.getOutput(1).getValue()));
  SendRequest request7=SendRequest.to(notMyAddr,Utils.COIN.subtract(Utils.CENT.subtract(BigInteger.valueOf(2)).multiply(BigInteger.valueOf(2))));
  request7.tx.addOutput(Utils.CENT.subtract(BigInteger.ONE),notMyAddr);
  assertTrue(wallet.completeTx(request7));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request7.fee);
  Transaction spend7=request7.tx;
  assertEquals(3,spend7.getOutputs().size());
  assertEquals(spend7.getOutput(0).getValue().add(spend7.getOutput(1).getValue()).add(spend7.getOutput(2).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request8=SendRequest.to(notMyAddr,Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  assertTrue(wallet.completeTx(request8));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request8.fee);
  Transaction spend8=request8.tx;
  assertEquals(1,spend8.getOutputs().size());
  assertEquals(spend8.getOutput(0).getValue(),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request9=SendRequest.to(notMyAddr,Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)));
  assertTrue(wallet.completeTx(request9));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT),request9.fee);
  Transaction spend9=request9.tx;
  assertEquals(1,spend9.getOutputs().size());
  assertEquals(spend9.getOutput(0).getValue(),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)));
  SendRequest request10=SendRequest.to(notMyAddr,Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(BigInteger.ONE)));
  assertTrue(wallet.completeTx(request10));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request10.fee);
  Transaction spend10=request10.tx;
  assertEquals(2,spend10.getOutputs().size());
  assertEquals(spend10.getOutput(0).getValue().add(spend10.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request11=SendRequest.to(notMyAddr,Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(BigInteger.valueOf(2))));
  request11.fee=Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE);
  assertTrue(wallet.completeTx(request11));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE),request11.fee);
  Transaction spend11=request11.tx;
  assertEquals(2,spend11.getOutputs().size());
  assertEquals(spend11.getOutput(0).getValue().add(spend11.getOutput(1).getValue()),Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE)));
  wallet.commitTx(spend11);
  Transaction tx5=createFakeTx(params,Utils.CENT,myAddress);
  wallet.receiveFromBlock(tx5,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  assertEquals(Utils.CENT,wallet.getBalance());
  for (int i=0; i < 100; i++) {
    block=new StoredBlock(makeSolvedTestBlock(blockStore,notMyAddr),BigInteger.ONE,1);
    wallet.notifyNewBestBlock(block);
  }
  block=new StoredBlock(makeSolvedTestBlock(blockStore,notMyAddr),BigInteger.ONE,1);
  Transaction tx6=createFakeTx(params,Utils.COIN,myAddress);
  wallet.receiveFromBlock(tx6,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  assertTrue(tx5.getOutput(0).isMine(wallet) && tx5.getOutput(0).isAvailableForSpending() && tx5.getConfidence().getDepthInBlocks() == 100);
  assertTrue(tx6.getOutput(0).isMine(wallet) && tx6.getOutput(0).isAvailableForSpending() && tx6.getConfidence().getDepthInBlocks() == 1);
  Transaction spend12=wallet.createSend(notMyAddr,Utils.CENT);
  assertTrue(spend12.getOutputs().size() == 2 && spend12.getOutput(0).getValue().add(spend12.getOutput(1).getValue()).equals(Utils.COIN));
  wallet.notifyNewBestBlock(block);
  assertTrue(tx5.getOutput(0).isMine(wallet) && tx5.getOutput(0).isAvailableForSpending() && tx5.getConfidence().getDepthInBlocks() == 101);
  assertTrue(tx6.getOutput(0).isMine(wallet) && tx6.getOutput(0).isAvailableForSpending() && tx6.getConfidence().getDepthInBlocks() == 1);
  Transaction spend13=wallet.createSend(notMyAddr,Utils.CENT);
  assertTrue(spend13.getOutputs().size() == 1 && spend13.getOutput(0).getValue().equals(Utils.CENT));
  block=new StoredBlock(makeSolvedTestBlock(blockStore,notMyAddr),BigInteger.ONE,1);
  wallet.notifyNewBestBlock(block);
  assertTrue(tx5.getOutput(0).isMine(wallet) && tx5.getOutput(0).isAvailableForSpending() && tx5.getConfidence().getDepthInBlocks() == 102);
  assertTrue(tx6.getOutput(0).isMine(wallet) && tx6.getOutput(0).isAvailableForSpending() && tx6.getConfidence().getDepthInBlocks() == 2);
  Transaction spend14=wallet.createSend(notMyAddr,Utils.CENT);
  assertTrue(spend14.getOutputs().size() == 2 && spend14.getOutput(0).getValue().add(spend14.getOutput(1).getValue()).equals(Utils.COIN));
  SendRequest request15=SendRequest.to(notMyAddr,Utils.CENT);
  for (int i=0; i < 29; i++)   request15.tx.addOutput(Utils.CENT,notMyAddr);
  assertTrue(request15.tx.bitcoinSerialize().length > 1000);
  request15.feePerKb=BigInteger.ONE;
  assertTrue(wallet.completeTx(request15));
  assertEquals(BigInteger.valueOf(2),request15.fee);
  Transaction spend15=request15.tx;
  assertEquals(31,spend15.getOutputs().size());
  BigInteger outValue15=BigInteger.ZERO;
  for (  TransactionOutput out : spend15.getOutputs())   outValue15=outValue15.add(out.getValue());
  assertEquals(Utils.COIN.subtract(BigInteger.valueOf(2)),outValue15);
  SendRequest request16=SendRequest.to(notMyAddr,Utils.CENT);
  request16.feePerKb=BigInteger.ZERO;
  for (int i=0; i < 29; i++)   request16.tx.addOutput(Utils.CENT,notMyAddr);
  assertTrue(request16.tx.bitcoinSerialize().length > 1000);
  assertTrue(wallet.completeTx(request16));
  assertEquals(BigInteger.ZERO,request16.fee);
  Transaction spend16=request16.tx;
  assertEquals(31,spend16.getOutputs().size());
  BigInteger outValue16=BigInteger.ZERO;
  for (  TransactionOutput out : spend16.getOutputs())   outValue16=outValue16.add(out.getValue());
  assertEquals(Utils.COIN,outValue16);
  SendRequest request17=SendRequest.to(notMyAddr,Utils.CENT);
  for (int i=0; i < 22; i++)   request17.tx.addOutput(Utils.CENT,notMyAddr);
  request17.tx.addOutput(new TransactionOutput(params,request17.tx,Utils.CENT,new byte[15]));
  request17.feePerKb=BigInteger.ONE;
  assertTrue(wallet.completeTx(request17));
  assertEquals(BigInteger.ONE,request17.fee);
  assertEquals(1,request17.tx.getInputs().size());
  int theoreticalMaxLength17=request17.tx.bitcoinSerialize().length + myKey.getPubKey().length + 75;
  for (  TransactionInput in : request17.tx.getInputs())   theoreticalMaxLength17-=in.getScriptBytes().length;
  assertEquals(999,theoreticalMaxLength17);
  Transaction spend17=request17.tx;
{
    final int length=spend17.bitcoinSerialize().length;
    assertTrue(Integer.toString(length),length >= 997 && length <= 999);
  }
  assertEquals(25,spend17.getOutputs().size());
  BigInteger outValue17=BigInteger.ZERO;
  for (  TransactionOutput out : spend17.getOutputs())   outValue17=outValue17.add(out.getValue());
  assertEquals(Utils.COIN.subtract(BigInteger.ONE),outValue17);
  SendRequest request18=SendRequest.to(notMyAddr,Utils.CENT);
  for (int i=0; i < 22; i++)   request18.tx.addOutput(Utils.CENT,notMyAddr);
  request18.tx.addOutput(new TransactionOutput(params,request18.tx,Utils.CENT,new byte[17]));
  request18.feePerKb=BigInteger.ONE;
  assertTrue(wallet.completeTx(request18));
  assertEquals(BigInteger.valueOf(2),request18.fee);
  assertEquals(1,request18.tx.getInputs().size());
  Transaction spend18=request18.tx;
  int theoreticalMaxLength18=spend18.bitcoinSerialize().length + myKey.getPubKey().length + 75;
  for (  TransactionInput in : spend18.getInputs())   theoreticalMaxLength18-=in.getScriptBytes().length;
  assertEquals(1001,theoreticalMaxLength18);
  assertTrue(spend18.bitcoinSerialize().length >= 998);
  assertTrue(spend18.bitcoinSerialize().length <= 1001);
  assertEquals(25,spend18.getOutputs().size());
  BigInteger outValue18=BigInteger.ZERO;
  for (  TransactionOutput out : spend18.getOutputs())   outValue18=outValue18.add(out.getValue());
  assertEquals(outValue18,Utils.COIN.subtract(BigInteger.valueOf(2)));
  assertEquals(wallet.getBalance(),Utils.CENT.add(Utils.COIN));
  SendRequest request19=SendRequest.to(notMyAddr,Utils.CENT);
  request19.feePerKb=BigInteger.ZERO;
  for (int i=0; i < 99; i++)   request19.tx.addOutput(Utils.CENT,notMyAddr);
  assertTrue(wallet.completeTx(request19));
  assertEquals(BigInteger.ZERO,request19.fee);
  assertEquals(1,request19.tx.getInputs().size());
  assertEquals(100,request19.tx.getOutputs().size());
  request19.tx.clearInputs();
  request19=SendRequest.forTx(request19.tx);
  request19.feePerKb=BigInteger.ONE;
  assertTrue(wallet.completeTx(request19));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request19.fee);
  assertEquals(2,request19.tx.getInputs().size());
  BigInteger outValue19=BigInteger.ZERO;
  for (  TransactionOutput out : request19.tx.getOutputs())   outValue19=outValue19.add(out.getValue());
  assertEquals(request19.tx.getOutput(request19.tx.getOutputs().size() - 1).getValue(),Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  assertEquals(outValue19,Utils.COIN.add(Utils.CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request20=SendRequest.to(notMyAddr,Utils.CENT);
  request20.feePerKb=BigInteger.ZERO;
  for (int i=0; i < 99; i++)   request20.tx.addOutput(Utils.CENT,notMyAddr);
  assertTrue(wallet.completeTx(request20));
  assertEquals(BigInteger.ZERO,request20.fee);
  assertEquals(1,request20.tx.getInputs().size());
  assertEquals(100,request20.tx.getOutputs().size());
  request20.tx.clearInputs();
  request20=SendRequest.forTx(request20.tx);
  request20.feePerKb=Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
  assertTrue(wallet.completeTx(request20));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(4)),request20.fee);
  assertEquals(2,request20.tx.getInputs().size());
  BigInteger outValue20=BigInteger.ZERO;
  for (  TransactionOutput out : request20.tx.getOutputs())   outValue20=outValue20.add(out.getValue());
  assertEquals(outValue20,Utils.COIN.add(Utils.CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(4))));
  SendRequest request21=SendRequest.to(notMyAddr,Utils.CENT);
  request21.feePerKb=BigInteger.ZERO;
  for (int i=0; i < 99; i++)   request21.tx.addOutput(Utils.CENT,notMyAddr);
  request21.tx.addOutput(Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE),notMyAddr);
  assertTrue(wallet.completeTx(request21));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE,request21.fee);
  assertEquals(2,request21.tx.getInputs().size());
  BigInteger outValue21=BigInteger.ZERO;
  for (  TransactionOutput out : request21.tx.getOutputs())   outValue21=outValue21.add(out.getValue());
  assertEquals(outValue21,Utils.COIN.add(Utils.CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
  SendRequest request25=SendRequest.to(notMyAddr,Utils.CENT);
  request25.feePerKb=BigInteger.ZERO;
  for (int i=0; i < 70; i++)   request25.tx.addOutput(Utils.CENT,notMyAddr);
  assertTrue(wallet.completeTx(request25));
  assertEquals(BigInteger.ZERO,request25.fee);
  assertEquals(1,request25.tx.getInputs().size());
  assertEquals(72,request25.tx.getOutputs().size());
  request25.tx.clearInputs();
  request25=SendRequest.forTx(request25.tx);
  request25.feePerKb=Utils.CENT.divide(BigInteger.valueOf(3));
  request25.ensureMinRequiredFee=false;
  assertTrue(wallet.completeTx(request25));
  assertEquals(Utils.CENT.subtract(BigInteger.ONE),request25.fee);
  assertEquals(2,request25.tx.getInputs().size());
  BigInteger outValue25=BigInteger.ZERO;
  for (  TransactionOutput out : request25.tx.getOutputs())   outValue25=outValue25.add(out.getValue());
  assertEquals(BigInteger.ONE,request25.tx.getOutput(request25.tx.getOutputs().size() - 1).getValue());
  assertEquals(outValue25,Utils.COIN.add(BigInteger.ONE));
  Transaction spendTx5=new Transaction(params);
  spendTx5.addOutput(Utils.CENT,notMyAddr);
  spendTx5.addInput(tx5.getOutput(0));
  spendTx5.signInputs(SigHash.ALL,wallet);
  wallet.receiveFromBlock(spendTx5,block,AbstractBlockChain.NewBlockType.BEST_CHAIN);
  assertEquals(Utils.COIN,wallet.getBalance());
  SendRequest request26=SendRequest.to(notMyAddr,Utils.CENT);
  for (int i=0; i < 98; i++)   request26.tx.addOutput(Utils.CENT,notMyAddr);
  request26.tx.addOutput(Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)),notMyAddr);
  assertTrue(request26.tx.bitcoinSerialize().length > 1000);
  request26.feePerKb=BigInteger.ONE;
  assertTrue(wallet.completeTx(request26));
  assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT),request26.fee);
  Transaction spend26=request26.tx;
  assertEquals(100,spend26.getOutputs().size());
  BigInteger outValue26=BigInteger.ZERO;
  for (  TransactionOutput out : spend26.getOutputs())   outValue26=outValue26.add(out.getValue());
  assertEquals(outValue26,Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)));
}