<commit_before>package com.luminiasoft.bitshares;

import android.util.Log;

import com.google.common.primitives.Bytes;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
import com.luminiasoft.bitshares.interfaces.JsonSerializable;

import org.bitcoinj.core.DumpedPrivateKey;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Utils;

import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

/**
 * Class used to represent a generic graphene transaction.
 */
public class Transaction implements ByteSerializable, JsonSerializable {
    private final String TAG = this.getClass().getName();

    public static final String KEY_EXPIRATION = "expiration";
    public static final String KEY_SIGNATURES = "signatures";
    public static final String KEY_OPERATIONS = "operations";
    public static final String KEY_EXTENSIONS = "extensions";
    public static final String KEY_REF_BLOCK_NUM = "ref_block_num";
    public static final String KEY_REF_BLOCK_PREFIX = "ref_block_prefix";

    private ECKey privateKey;
    private BlockData blockData;
    private List<BaseOperation> operations;
    private List<Extension> extensions;

    /**
     * Transaction constructor.
     * @param wif: The user's private key in the base58 format.
     * @param block_data: Block data containing important information used to sign a transaction.
     * @param operation_list: List of operations to include in the transaction.
     */
    public Transaction(String wif, BlockData block_data, List<BaseOperation> operation_list){
        this.privateKey = DumpedPrivateKey.fromBase58(null, wif).getKey();
        this.blockData = block_data;
        this.operations = operation_list;
        this.extensions = new ArrayList<Extension>();
    }

    /**
     * Transaction constructor.
     * @param privateKey : Instance of a ECKey containing the private key that will be used to sign this transaction.
     * @param blockData : Block data containing important information used to sign a transaction.
     * @param operationList : List of operations to include in the transaction.
     */
    public Transaction(ECKey privateKey, BlockData blockData, List<BaseOperation> operationList){
        this.privateKey = privateKey;
        this.blockData = blockData;
        this.operations = operationList;
        this.extensions = new ArrayList<Extension>();
    }

    public ECKey getPrivateKey(){
        return this.privateKey;
    }

    /**
     * Obtains a signature of this transaction.
     * @return: A valid signature of the current transaction.
     */
    public byte[] getSignature(){
        byte[] serializedTransaction = this.toBytes();
        Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
        boolean isCanonical = false;
        int recId = -1;
        ECKey.ECDSASignature sig = null;
        while(!isCanonical) {
            sig = privateKey.sign(hash);
            Log.d(TAG,"signature is canonical: "+sig.isCanonical());
            if(!sig.isCanonical()){
                // Signature was not canonical, retrying
                continue;
            }else{
                // Signature is canonical
                isCanonical = true;
            }
            // Now we have to work backwards to figure out the recId needed to recover the signature.
            for (int i = 0; i < 4; i++) {
                ECKey k = ECKey.recoverFromSignature(i, sig, hash, privateKey.isCompressed());
                if (k != null && k.getPubKeyPoint().equals(privateKey.getPubKeyPoint())) {
                    recId = i;
                    break;
                }else{
                    if(k == null){
                        Log.d(TAG, "Recovered key was null");
                    }
                    if(k.getPubKeyPoint().equals(privateKey.getPubKeyPoint())){
                        Log.d(TAG, "Recovered pub point is not equal to sk pub point");
                    }
                }
            }
        }
        int headerByte = recId + 27 + (privateKey.isCompressed() ? 4 : 0);
        byte[] sigData = new byte[65];  // 1 header + 32 bytes for R + 32 bytes for S
        sigData[0] = (byte)headerByte;
        System.arraycopy(Utils.bigIntegerToBytes(sig.r, 32), 0, sigData, 1, 32);
        System.arraycopy(Utils.bigIntegerToBytes(sig.s, 32), 0, sigData, 33, 32);
        return sigData;
    }

    /**
     * Method that creates a serialized byte array with compact information about this transaction
     * that is needed for the creation of a signature.
     * @return: byte array with serialized information about this transaction.
     */
    public byte[] toBytes(){
        // Creating a List of Bytes and adding the first bytes from the chain apiId
        List<Byte> byteArray = new ArrayList<Byte>();
        byteArray.addAll(Bytes.asList(Util.hexToBytes(Chains.BITSHARES.CHAIN_ID)));

        // Adding the block data
        byteArray.addAll(Bytes.asList(this.blockData.toBytes()));

        // Adding the number of operations
        byteArray.add((byte) this.operations.size());

        // Adding all the operations
        for(BaseOperation operation : operations){
            byteArray.add(operation.getId());
            byteArray.addAll(Bytes.asList(operation.toBytes()));
        }

        //Adding the number of extensions
        byteArray.add((byte) this.extensions.size());<commit_msg>Adding a getter and some logs<commit_after>package com.luminiasoft.bitshares;

import android.util.Log;

import com.google.common.primitives.Bytes;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
import com.luminiasoft.bitshares.interfaces.JsonSerializable;

import org.bitcoinj.core.DumpedPrivateKey;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Utils;

import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

/**
 * Class used to represent a generic graphene transaction.
 */
public class Transaction implements ByteSerializable, JsonSerializable {
    private final String TAG = this.getClass().getName();

    public static final String KEY_EXPIRATION = "expiration";
    public static final String KEY_SIGNATURES = "signatures";
    public static final String KEY_OPERATIONS = "operations";
    public static final String KEY_EXTENSIONS = "extensions";
    public static final String KEY_REF_BLOCK_NUM = "ref_block_num";
    public static final String KEY_REF_BLOCK_PREFIX = "ref_block_prefix";

    private ECKey privateKey;
    private BlockData blockData;
    private List<BaseOperation> operations;
    private List<Extension> extensions;

    /**
     * Transaction constructor.
     * @param wif: The user's private key in the base58 format.
     * @param block_data: Block data containing important information used to sign a transaction.
     * @param operation_list: List of operations to include in the transaction.
     */
    public Transaction(String wif, BlockData block_data, List<BaseOperation> operation_list){
        this.privateKey = DumpedPrivateKey.fromBase58(null, wif).getKey();
        this.blockData = block_data;
        this.operations = operation_list;
        this.extensions = new ArrayList<Extension>();
    }

    /**
     * Transaction constructor.
     * @param privateKey : Instance of a ECKey containing the private key that will be used to sign this transaction.
     * @param blockData : Block data containing important information used to sign a transaction.
     * @param operationList : List of operations to include in the transaction.
     */
    public Transaction(ECKey privateKey, BlockData blockData, List<BaseOperation> operationList){
        this.privateKey = privateKey;
        this.blockData = blockData;
        this.operations = operationList;
        this.extensions = new ArrayList<Extension>();
    }

    public ECKey getPrivateKey(){
        return this.privateKey;
    }

    public List<BaseOperation> getOperations(){ return this.operations; }

    /**
     * Obtains a signature of this transaction.
     * @return: A valid signature of the current transaction.
     */
    public byte[] getSignature(){
        Log.d(TAG,"getSignature");
        byte[] serializedTransaction = this.toBytes();
        Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
        boolean isCanonical = false;
        int recId = -1;
        ECKey.ECDSASignature sig = null;
        while(!isCanonical) {
            sig = privateKey.sign(hash);
            Log.d(TAG,"signature is canonical: "+sig.isCanonical());
            if(!sig.isCanonical()){
                // Signature was not canonical, retrying
                continue;
            }else{
                // Signature is canonical
                isCanonical = true;
            }
            // Now we have to work backwards to figure out the recId needed to recover the signature.
            for (int i = 0; i < 4; i++) {
                ECKey k = ECKey.recoverFromSignature(i, sig, hash, privateKey.isCompressed());
                if (k != null && k.getPubKeyPoint().equals(privateKey.getPubKeyPoint())) {
                    recId = i;
                    break;
                }else{
                    if(k == null){
                        Log.d(TAG, "Recovered key was null");
                    }
                    if(k.getPubKeyPoint().equals(privateKey.getPubKeyPoint())){
                        Log.d(TAG, "Recovered pub point is not equal to sk pub point");
                    }
                }
            }
        }
        int headerByte = recId + 27 + (privateKey.isCompressed() ? 4 : 0);
        byte[] sigData = new byte[65];  // 1 header + 32 bytes for R + 32 bytes for S
        sigData[0] = (byte)headerByte;
        System.arraycopy(Utils.bigIntegerToBytes(sig.r, 32), 0, sigData, 1, 32);
        System.arraycopy(Utils.bigIntegerToBytes(sig.s, 32), 0, sigData, 33, 32);
        Log.d(TAG, "Signature: "+Util.bytesToHex(sigData));
        return sigData;
    }

    /**
     * Method that creates a serialized byte array with compact information about this transaction
     * that is needed for the creation of a signature.
     * @return: byte array with serialized information about this transaction.
     */
    public byte[] toBytes(){
        // Creating a List of Bytes and adding the first bytes from the chain apiId
        List<Byte> byteArray = new ArrayList<Byte>();
        byteArray.addAll(Bytes.asList(Util.hexToBytes(Chains.BITSHARES.CHAIN_ID)));

        // Adding the block data
        byteArray.addAll(Bytes.asList(this.blockData.toBytes()));

        // Adding the number of operations
        byteArray.add((byte) this.operations.size());

        // Adding all the operations
        for(BaseOperation operation : operations){
            byteArray.add(operation.getId());
            byteArray.addAll(Bytes.asList(operation.toBytes()));
        }

        //Adding the number of extensions
        byteArray.add((byte) this.extensions.size());
{'fraction_non_alphanumeric': 0.09547008547008547, 'fraction_numerical': 0.007521367521367521, 'mean_word_length': 2.6417678182384066, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5105542', 'n_tokens_mistral': 3250, 'n_tokens_neox': 3108, 'n_words': 911}