package com.oraclechain.eosio.chain; import com.google.gson.annotations.Expose; import com.oraclechain.eosio.crypto.util.HexUtils; import com.oraclechain.eosio.eosTypes.EosByteWriter; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.List; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; /** * Created by swapnibble on 2018-03-19. */ public class PackedTransaction { public enum CompressType{ none, zlib } @Expose final List<String> signatures ; @Expose final String compression; @Expose private String packed_context_free_data; @Expose private String packed_trx; public PackedTransaction(SignedTransaction stxn, CompressType compressType){ compression = compressType.name(); signatures = stxn.getSignatures(); packed_trx = HexUtils.toHex( packTransaction( stxn, compressType) ); byte[] packed_ctx_free_bytes = packContextFreeData( stxn.getCtxFreeData(), compressType ); packed_context_free_data = ( packed_ctx_free_bytes.length == 0 ) ? "" : HexUtils.toHex( packed_ctx_free_bytes ); } private byte[] packTransaction( Transaction transaction, CompressType compressType ) { EosByteWriter byteWriter = new EosByteWriter(512); transaction.pack(byteWriter); // pack -> compress return compress( byteWriter.toBytes(), compressType ) ; } private byte[] packContextFreeData( List<String> ctxFreeData, CompressType compressType ){ EosByteWriter byteWriter = new EosByteWriter(64); int ctxFreeDataCount = ( ctxFreeData == null ) ? 0 : ctxFreeData.size(); if ( ctxFreeDataCount == 0 ){ return byteWriter.toBytes(); } byteWriter.putVariableUInt( ctxFreeDataCount); for ( String hexData : ctxFreeData ) { byteWriter.putBytes( HexUtils.toBytes( hexData)); } return compress( byteWriter.toBytes(), compressType ) ; } public PackedTransaction(SignedTransaction stxn){ this( stxn, CompressType.none); } // public long getDataSize() { // return data.length() / 2; // hex -> raw bytes // } private byte[] compress( byte[] uncompressedBytes, CompressType compressType) { if ( compressType == null || !CompressType.zlib.equals( compressType)) { return uncompressedBytes; } // zip! Deflater deflater = new Deflater( Deflater.BEST_COMPRESSION ); deflater.setInput( uncompressedBytes ); ByteArrayOutputStream outputStream = new ByteArrayOutputStream( uncompressedBytes.length); deflater.finish(); byte[] buffer = new byte[1024]; while (!deflater.finished()) { int count = deflater.deflate(buffer); // returns the generated code... index outputStream.write(buffer, 0, count); } try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); return uncompressedBytes; } return outputStream.toByteArray(); } private byte[] decompress( byte [] compressedBytes ) { Inflater inflater = new Inflater(); inflater.setInput( compressedBytes ); ByteArrayOutputStream outputStream = new ByteArrayOutputStream( compressedBytes.length); byte[] buffer = new byte[1024]; try { while (!inflater.finished()) { int count = inflater.inflate(buffer); outputStream.write(buffer, 0, count); } outputStream.close(); } catch (DataFormatException | IOException e) { e.printStackTrace(); return compressedBytes; } return outputStream.toByteArray(); } }