SubTxTopup extends SpecialTxPayload { @Override public Sha256Hash getHash() { try { UnsafeByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(getMessageSize()); bitcoinSerializeToStream(bos); return Sha256Hash.wrapReversed(Sha256Hash.hashTwice(bos.toByteArray())); } catch (IOException x) { throw new RuntimeException(x); } } SubTxTopup(NetworkParameters params, Transaction tx);  SubTxTopup(int version, Sha256Hash regTxId); @Override Sha256Hash getHash(); JSONObject toJson(); @Override int getCurrentVersion(); @Override Transaction.Type getType(); @Override String getName(); Sha256Hash getRegTxId(); final int CURRENT_VERSION; final int MESSAGE_SIZE; static final Coin MIN_SUBTX_TOPUP; }
@Test public void createSubTxTopup() { Sha256Hash blockchainUserRegistrationTransactionHash = Sha256Hash.wrap("b4225e4d2268c99eeb89198e7c37e3375060fb1ea35c5ce2336b0772edfc6923"); Sha256Hash inputId = Sha256Hash.wrap("f6deacdfeb363d22398b913bdcd080adf5f4534716478ad220a10dc43e07add4"); Address outputAddress = Address.fromBase58(PARAMS, "yP8JPjWoc2u8rSN6F4eE5FQn3nQiQJ9jDs"); Sha256Hash txId = Sha256Hash.wrap("715f96a80e0e4feb8a94f2e9f4f6821dd4502f0ae6c43013ec6e77985d059b55"); Address inputAddress = Address.fromBase58(PARAMS, "yYZqfmQhqMSF1PL7xeNHzQM3q9rktXFPLN"); String inputPrivateKey = "cNYPkC4hGoE11ieBr2GgwyUct8zY1HLi5S5K2LLPMewtQGJsbu9H"; ECKey privateKey = DumpedPrivateKey.fromBase58(PARAMS, inputPrivateKey).getKey(); Transaction tx = new Transaction(PARAMS); tx.setVersion(3); tx.setType(Transaction.Type.TRANSACTION_SUBTX_TOPUP); TransactionOutPoint outpoint = new TransactionOutPoint(PARAMS, 0, inputId); TransactionInput txin = new TransactionInput(PARAMS, null, new byte[0], outpoint); txin.setSequenceNumber(TransactionInput.NO_SEQUENCE-1); TransactionOutput output = new TransactionOutput(PARAMS, null, Coin.valueOf(24899998674L), ScriptBuilder.createOutputScript(outputAddress).getProgram()); TransactionOutput outputOpReturn = new TransactionOutput(PARAMS, null, Coin.valueOf(100000000), new ScriptBuilder().op(OP_RETURN).build().getProgram()); tx.addOutput(outputOpReturn); tx.addOutput(output); SubTxTopup subtx = new SubTxTopup(1, blockchainUserRegistrationTransactionHash); tx.setExtraPayload(subtx.getPayload()); tx.addSignedInput(txin, ScriptBuilder.createOutputScript(inputAddress), privateKey, Transaction.SigHash.ALL, false); assertEquals(txId, tx.getHash()); byte [] inputScript = Utils.HEX.decode("483045022100a65429d4f2ab2df58cafdaaffe874ef260f610e068e89a4455fbf92261156bb7022015733ae5aef3006fd5781b91f97ca1102edf09e9383ca761e407c619d13db7660121034c1f31446c5971558b9027499c3678483b0deb06af5b5ccd41e1f536af1e34ca"); assertArrayEquals("The transaction input signature isn't signing correctly", inputScript, tx.getInput(0).getScriptBytes()); try { UnsafeByteArrayOutputStream stream = new UnsafeByteArrayOutputStream(txdata.length); tx.bitcoinSerialize(stream); assertArrayEquals("Blockchain user transaction does not match it's data", txdata, stream.toByteArray()); } catch (IOException x) { fail(); } }