@Test public void opReturnOneOutputWithValueTest() throws Exception { // Tests basic send of transaction with one output that destroys coins and has an OP_RETURN. receiveATransaction(wallet, myAddress); Transaction tx = new Transaction(PARAMS); Coin messagePrice = CENT; Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes()); tx.addOutput(messagePrice, script); SendRequest request = SendRequest.forTx(tx); wallet.completeTx(request); }
@Test public void opReturnOneOutputTest() throws Exception { // Tests basic send of transaction with one output that doesn't transfer any value but just writes OP_RETURN. receiveATransaction(wallet, myAddress); Transaction tx = new Transaction(PARAMS); Coin messagePrice = Coin.ZERO; Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes()); tx.addOutput(messagePrice, script); SendRequest request = SendRequest.forTx(tx); request.ensureMinRequiredFee = true; wallet.completeTx(request); }
@Test(expected = Wallet.ExceededMaxTransactionSize.class) public void respectMaxStandardSize() throws Exception { // Check that we won't create txns > 100kb. Average tx size is ~220 bytes so this would have to be enormous. sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, valueOf(100, 0)); Transaction tx = new Transaction(PARAMS); byte[] bits = new byte[20]; new Random().nextBytes(bits); Coin v = CENT; // 3100 outputs to a random address. for (int i = 0; i < 3100; i++) { tx.addOutput(v, new Address(PARAMS, bits)); } SendRequest req = SendRequest.forTx(tx); wallet.completeTx(req); }
@Test(expected = Wallet.DustySendRequested.class) public void sendDustTest() throws InsufficientMoneyException { // Tests sending dust, should throw DustySendRequested. Transaction tx = new Transaction(PARAMS); tx.addOutput(Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI), OTHER_ADDRESS); SendRequest request = SendRequest.forTx(tx); request.ensureMinRequiredFee = true; wallet.completeTx(request); }
@Test (expected = TransactionSigner.MissingSignatureException.class) public void completeTxPartiallySignedMarriedThrowsByDefault() throws Exception { createMarriedWallet(2, 2, false); myAddress = wallet.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS); sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, COIN, myAddress); SendRequest req = SendRequest.emptyWallet(OTHER_ADDRESS); wallet.completeTx(req); }
@Test(expected = Wallet.MultipleOpReturnRequested.class) public void twoOpReturnsPerTransactionTest() throws Exception { // Tests sending transaction where there are 2 attempts to write OP_RETURN scripts - this should fail and throw MultipleOpReturnRequested. receiveATransaction(wallet, myAddress); Transaction tx = new Transaction(PARAMS); Coin messagePrice = Coin.ZERO; Script script1 = ScriptBuilder.createOpReturnScript("hello world 1!".getBytes()); Script script2 = ScriptBuilder.createOpReturnScript("hello world 2!".getBytes()); tx.addOutput(messagePrice, script1); tx.addOutput(messagePrice, script2); SendRequest request = SendRequest.forTx(tx); request.ensureMinRequiredFee = true; wallet.completeTx(request); }
@Test public void testEmptyRandomWallet() throws Exception { // Add a random set of outputs StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, OTHER_ADDRESS), BigInteger.ONE, 1); Random rng = new Random(); for (int i = 0; i < rng.nextInt(100) + 1; i++) { Transaction tx = createFakeTx(PARAMS, Coin.valueOf(rng.nextInt((int) COIN.value)), myAddress); wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i); } SendRequest request = SendRequest.emptyWallet(OTHER_ADDRESS); wallet.completeTx(request); wallet.commitTx(request.tx); assertEquals(ZERO, wallet.getBalance()); }
@Test public void opReturnTwoOutputsTest() throws Exception { // Tests sending transaction where one output transfers BTC, the other one writes OP_RETURN. receiveATransaction(wallet, myAddress); Transaction tx = new Transaction(PARAMS); Coin messagePrice = Coin.ZERO; Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes()); tx.addOutput(CENT, OTHER_ADDRESS); tx.addOutput(messagePrice, script); SendRequest request = SendRequest.forTx(tx); wallet.completeTx(request); }
@Test(expected = Wallet.DustySendRequested.class) public void sendDustAndOpReturnWithoutValueTest() throws Exception { // Tests sending dust and OP_RETURN without value, should throw DustySendRequested because sending sending dust is not allowed in any case. receiveATransactionAmount(wallet, myAddress, Coin.COIN); Transaction tx = new Transaction(PARAMS); tx.addOutput(Coin.ZERO, ScriptBuilder.createOpReturnScript("hello world!".getBytes())); tx.addOutput(Coin.SATOSHI, OTHER_ADDRESS); SendRequest request = SendRequest.forTx(tx); request.ensureMinRequiredFee = true; wallet.completeTx(request); }
@Test public void sendRequestMemo() throws Exception { receiveATransaction(wallet, myAddress); SendRequest sendRequest = SendRequest.to(myAddress, Coin.COIN); sendRequest.memo = "memo"; wallet.completeTx(sendRequest); assertEquals(sendRequest.memo, sendRequest.tx.getMemo()); }
public void completeTxPartiallySignedMarried(Wallet.MissingSigsMode missSigMode, byte[] expectedSig) throws Exception { // create married wallet without signer createMarriedWallet(2, 2, false); myAddress = wallet.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS); sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, COIN, myAddress); SendRequest req = SendRequest.emptyWallet(OTHER_ADDRESS); req.missingSigsMode = missSigMode; wallet.completeTx(req); TransactionInput input = req.tx.getInput(0); boolean firstSigIsMissing = Arrays.equals(expectedSig, input.getScriptSig().getChunks().get(1).data); boolean secondSigIsMissing = Arrays.equals(expectedSig, input.getScriptSig().getChunks().get(2).data); assertTrue("Only one of the signatures should be missing/dummy", firstSigIsMissing ^ secondSigIsMissing); int localSigIndex = firstSigIsMissing ? 2 : 1; int length = input.getScriptSig().getChunks().get(localSigIndex).data.length; assertTrue("Local sig should be present: " + length, length >= 70); }
@Test (expected = ECKey.MissingPrivateKeyException.class) public void completeTxPartiallySignedThrows() throws Exception { sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, wallet.freshReceiveKey()); SendRequest req = SendRequest.emptyWallet(OTHER_ADDRESS); wallet.completeTx(req); // Delete the sigs for (TransactionInput input : req.tx.getInputs()) input.clearScriptBytes(); Wallet watching = Wallet.fromWatchingKey(PARAMS, wallet.getWatchingKey().dropParent().dropPrivateBytes()); watching.completeTx(SendRequest.forTx(req.tx)); }
@Test(expected = Wallet.DustySendRequested.class) public void sendDustAndMessageWithValueTest() throws Exception { // Tests sending dust and OP_RETURN with value, should throw DustySendRequested receiveATransaction(wallet, myAddress); Transaction tx = new Transaction(PARAMS); tx.addOutput(Coin.CENT, ScriptBuilder.createOpReturnScript("hello world!".getBytes())); tx.addOutput(Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI), OTHER_ADDRESS); SendRequest request = SendRequest.forTx(tx); request.ensureMinRequiredFee = true; wallet.completeTx(request); }
@Test public void opReturnMaxBytes() throws Exception { receiveATransaction(wallet, myAddress); Transaction tx = new Transaction(PARAMS); Script script = ScriptBuilder.createOpReturnScript(new byte[80]); tx.addOutput(Coin.ZERO, script); SendRequest request = SendRequest.forTx(tx); request.ensureMinRequiredFee = true; wallet.completeTx(request); }
@Test public void sendRequestExchangeRate() throws Exception { receiveATransaction(wallet, myAddress); SendRequest sendRequest = SendRequest.to(myAddress, Coin.COIN); sendRequest.exchangeRate = new ExchangeRate(Fiat.parseFiat("EUR", "500")); wallet.completeTx(sendRequest); assertEquals(sendRequest.exchangeRate, sendRequest.tx.getExchangeRate()); }
@Test public void testMultiSigOutputToString() throws Exception { sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, Coin.COIN); ECKey myKey = new ECKey(); this.wallet.importKey(myKey); // Simulate another signatory ECKey otherKey = new ECKey(); // Create multi-sig transaction Transaction multiSigTransaction = new Transaction(PARAMS); ImmutableList<ECKey> keys = ImmutableList.of(myKey, otherKey); Script scriptPubKey = ScriptBuilder.createMultiSigOutputScript(2, keys); multiSigTransaction.addOutput(Coin.COIN, scriptPubKey); SendRequest req = SendRequest.forTx(multiSigTransaction); this.wallet.completeTx(req); TransactionOutput multiSigTransactionOutput = multiSigTransaction.getOutput(0); assertThat(multiSigTransactionOutput.toString(), CoreMatchers.containsString("CHECKMULTISIG")); }
@Test public void sendMultipleCentsTest() throws Exception { receiveATransactionAmount(wallet, myAddress, Coin.COIN); Transaction tx = new Transaction(PARAMS); Coin c = CENT.subtract(SATOSHI); tx.addOutput(c, OTHER_ADDRESS); tx.addOutput(c, OTHER_ADDRESS); tx.addOutput(c, OTHER_ADDRESS); tx.addOutput(c, OTHER_ADDRESS); SendRequest request = SendRequest.forTx(tx); wallet.completeTx(request); }
@Test public void transactionGetFeeTest() throws Exception { // Prepare wallet to spend StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, OTHER_ADDRESS), BigInteger.ONE, 1); Transaction tx = createFakeTx(PARAMS, COIN, myAddress); wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); // Create a transaction SendRequest request = SendRequest.to(OTHER_ADDRESS, CENT); request.feePerKb = Transaction.DEFAULT_TX_FEE; wallet.completeTx(request); assertEquals(Coin.valueOf(11350), request.tx.getFee()); }
@Test public void totalReceivedSent() throws Exception { // Receive 4 BTC in 2 separate transactions Transaction toMe1 = createFakeTxWithoutChangeAddress(PARAMS, COIN.multiply(2), myAddress); Transaction toMe2 = createFakeTxWithoutChangeAddress(PARAMS, COIN.multiply(2), myAddress); sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, toMe1, toMe2); // Check we calculate the total received correctly assertEquals(Coin.COIN.multiply(4), wallet.getTotalReceived()); // Send 3 BTC in a single transaction SendRequest req = SendRequest.to(OTHER_ADDRESS, Coin.COIN.multiply(3)); wallet.completeTx(req); sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, req.tx); // Check that we still have the same totalReceived, since the above tx will have sent us change back assertEquals(Coin.COIN.multiply(4),wallet.getTotalReceived()); assertEquals(Coin.COIN.multiply(3),wallet.getTotalSent()); // TODO: test shared wallet calculation here } }
@Test public void testStandardWalletDisconnect() throws Exception { NetworkParameters params = UnitTestParams.get(); Wallet w = new Wallet(new Context(params)); w.setCoinSelector(new AllowUnconfirmedCoinSelector()); Address a = w.currentReceiveAddress(); Transaction tx1 = FakeTxBuilder.createFakeTxWithoutChangeAddress(params, Coin.COIN, a); w.receivePending(tx1, null); Transaction tx2 = new Transaction(params); tx2.addOutput(Coin.valueOf(99000000), new ECKey()); w.completeTx(SendRequest.forTx(tx2)); TransactionInput txInToDisconnect = tx2.getInput(0); assertEquals(tx1, txInToDisconnect.getOutpoint().fromTx); assertNull(txInToDisconnect.getOutpoint().connectedOutput); txInToDisconnect.disconnect(); assertNull(txInToDisconnect.getOutpoint().fromTx); assertNull(txInToDisconnect.getOutpoint().connectedOutput); }