BitcoinUtil { public static byte[] getTransactionHash(BitcoinTransaction transaction) throws IOException{ ByteArrayOutputStream transactionBAOS = new ByteArrayOutputStream(); byte[] version = reverseByteArray(convertIntToByteArray(transaction.getVersion())); transactionBAOS.write(version); byte[] inCounter = transaction.getInCounter(); transactionBAOS.write(inCounter); for (int i=0;i<transaction.getListOfInputs().size();i++) { transactionBAOS.write(transaction.getListOfInputs().get(i).getPrevTransactionHash()); transactionBAOS.write(reverseByteArray(convertIntToByteArray((int)(transaction.getListOfInputs().get(i).getPreviousTxOutIndex())))); transactionBAOS.write(transaction.getListOfInputs().get(i).getTxInScriptLength()); transactionBAOS.write(transaction.getListOfInputs().get(i).getTxInScript()); transactionBAOS.write(reverseByteArray(convertIntToByteArray((int)(transaction.getListOfInputs().get(i).getSeqNo())))); } byte[] outCounter = transaction.getOutCounter(); transactionBAOS.write(outCounter); for (int j=0;j<transaction.getListOfOutputs().size();j++) { transactionBAOS.write(convertBigIntegerToByteArray(transaction.getListOfOutputs().get(j).getValue(),8)); transactionBAOS.write(transaction.getListOfOutputs().get(j).getTxOutScriptLength()); transactionBAOS.write(transaction.getListOfOutputs().get(j).getTxOutScript()); } byte[] lockTime=reverseByteArray(convertIntToByteArray(transaction.getLockTime())); transactionBAOS.write(lockTime); byte[] transactionByteArray= transactionBAOS.toByteArray(); byte[] firstRoundHash; byte[] secondRoundHash; try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); firstRoundHash = digest.digest(transactionByteArray); secondRoundHash = digest.digest(firstRoundHash); } catch (NoSuchAlgorithmException nsae) { LOG.error(nsae); return new byte[0]; } return secondRoundHash; } private  BitcoinUtil(); static long convertSignedIntToUnsigned(int signedInt); static byte[] convertIntToByteArray(int intToConvert); static byte[] convertLongToByteArray(long longToConvert); static byte[] convertBigIntegerToByteArray(BigInteger bigIntegerToConvert,int exactArraySize); static byte[] convertVarIntByteBufferToByteArray(ByteBuffer byteBuffer); static long convertVarIntByteBufferToLong(ByteBuffer byteBuffer); static BigInteger getVarIntBI(byte[] varInt); static long getVarInt(byte[] varInt); static byte getVarIntSize(byte firstByteVarInt); static long getSize(byte[] byteSize); static byte[] reverseByteArray(byte[] inputByteArray); static byte[] convertHexStringToByteArray(String hexString); static String convertByteArrayToHexString(byte[] byteArray); static Date convertIntToDate(int dateInt); static boolean compareMagics(byte[] magic1,byte[] magic2); static byte[] getTransactionHash(BitcoinTransaction transaction); static byte[] getTransactionHashSegwit(BitcoinTransaction transaction);  }
@Test public void getTransactionHash() throws NoSuchAlgorithmException, IOException { int version=1; byte[] inCounter = new byte[]{0x01}; byte[] previousTransactionHash = new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; long previousTxOutIndex = 4294967295L; byte[] txInScriptLength = new byte[]{(byte)0x4D}; byte[] txInScript= new byte[]{(byte)0x04,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x1D,(byte)0x01,(byte)0x04,(byte)0x45,(byte)0x54,(byte)0x68,(byte)0x65,(byte)0x20,(byte)0x54,(byte)0x69,(byte)0x6D,(byte)0x65,(byte)0x73,(byte)0x20,(byte)0x30,(byte)0x33,(byte)0x2F,(byte)0x4A,(byte)0x61,(byte)0x6E,(byte)0x2F,(byte)0x32,(byte)0x30,(byte)0x30,(byte)0x39,(byte)0x20,(byte)0x43,(byte)0x68,(byte)0x61,(byte)0x6E,(byte)0x63,(byte)0x65,(byte)0x6C,(byte)0x6C,(byte)0x6F,(byte)0x72,(byte)0x20,(byte)0x6F,(byte)0x6E,(byte)0x20,(byte)0x62,(byte)0x72,(byte)0x69,(byte)0x6E,(byte)0x6B,(byte)0x20,(byte)0x6F,(byte)0x66,(byte)0x20,(byte)0x73,(byte)0x65,(byte)0x63,(byte)0x6F,(byte)0x6E,(byte)0x64,(byte)0x20,(byte)0x62,(byte)0x61,(byte)0x69,(byte)0x6C,(byte)0x6F,(byte)0x75,(byte)0x74,(byte)0x20,(byte)0x66,(byte)0x6F,(byte)0x72,(byte)0x20,(byte)0x62,(byte)0x61,(byte)0x6E,(byte)0x6B,(byte)0x73}; long seqNo=4294967295L; byte[] outCounter = new byte[]{0x01}; long value=5000000000L; byte[] txOutScriptLength=new byte[]{(byte)0x43}; byte[] txOutScript=new byte[]{(byte)0x41,(byte)0x04,(byte)0x67,(byte)0x8A,(byte)0xFD,(byte)0xB0,(byte)0xFE,(byte)0x55,(byte)0x48,(byte)0x27,(byte)0x19,(byte)0x67,(byte)0xF1,(byte)0xA6,(byte)0x71,(byte)0x30,(byte)0xB7,(byte)0x10,(byte)0x5C,(byte)0xD6,(byte)0xA8,(byte)0x28,(byte)0xE0,(byte)0x39,(byte)0x09,(byte)0xA6,(byte)0x79,(byte)0x62,(byte)0xE0,(byte)0xEA,(byte)0x1F,(byte)0x61,(byte)0xDE,(byte)0xB6,(byte)0x49,(byte)0xF6,(byte)0xBC,(byte)0x3F,(byte)0x4C,(byte)0xEF,(byte)0x38,(byte)0xC4,(byte)0xF3,(byte)0x55,(byte)0x04,(byte)0xE5,(byte)0x1E,(byte)0xC1,(byte)0x12,(byte)0xDE,(byte)0x5C,(byte)0x38,(byte)0x4D,(byte)0xF7,(byte)0xBA,(byte)0x0B,(byte)0x8D,(byte)0x57,(byte)0x8A,(byte)0x4C,(byte)0x70,(byte)0x2B,(byte)0x6B,(byte)0xF1,(byte)0x1D,(byte)0x5F,(byte)0xAC}; int lockTime = 0; List<BitcoinTransactionInput> genesisInput = new ArrayList<BitcoinTransactionInput>(1); genesisInput.add(new BitcoinTransactionInput(previousTransactionHash,previousTxOutIndex,txInScriptLength,txInScript,seqNo)); List<BitcoinTransactionOutput> genesisOutput = new ArrayList<BitcoinTransactionOutput>(1); genesisOutput.add(new BitcoinTransactionOutput(BigInteger.valueOf(value),txOutScriptLength,txOutScript)); BitcoinTransaction genesisTransaction = new BitcoinTransaction(version,inCounter,genesisInput,outCounter,genesisOutput,lockTime); byte[] genesisTransactionHash=BitcoinUtil.getTransactionHash(genesisTransaction); byte[] expectedHash = BitcoinUtil.reverseByteArray(new byte[]{(byte)0x4A,(byte)0x5E,(byte)0x1E,(byte)0x4B,(byte)0xAA,(byte)0xB8,(byte)0x9F,(byte)0x3A,(byte)0x32,(byte)0x51,(byte)0x8A,(byte)0x88,(byte)0xC3,(byte)0x1B,(byte)0xC8,(byte)0x7F,(byte)0x61,(byte)0x8F,(byte)0x76,(byte)0x67,(byte)0x3E,(byte)0x2C,(byte)0xC7,(byte)0x7A,(byte)0xB2,(byte)0x12,(byte)0x7B,(byte)0x7A,(byte)0xFD,(byte)0xED,(byte)0xA3,(byte)0x3B}); assertArrayEquals( expectedHash, genesisTransactionHash,"Hash for Genesis Transaction correctly calculated"); }