All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.citahub.cita.utils.TransactionUtil Maven / Gradle / Ivy

The newest version!
package com.citahub.cita.utils;

import static com.citahub.cita.utils.Numeric.prependHexPrefix;

import java.math.BigInteger;
import java.security.SignatureException;

import com.citahub.cita.crypto.Keys;
import com.citahub.cita.crypto.Sign;
import com.citahub.cita.protobuf.Blockchain;
import com.citahub.cita.protobuf.ConvertStrByte;
import com.citahub.cita.protocol.core.methods.request.Transaction;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;

public class TransactionUtil {

    public static Blockchain.Transaction getTransaction(String content) {
        Blockchain.Transaction transaction = null;
        try {
            Blockchain.UnverifiedTransaction unverifiedTransaction =
                    Blockchain.UnverifiedTransaction.parseFrom(
                            ConvertStrByte.hexStringToBytes(content.substring(2)));
            transaction = unverifiedTransaction.getTransaction();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return transaction;
    }

    public static String getTo(String content) {
        Blockchain.Transaction transaction = getTransaction(content);
        return transaction.getTo();
    }

    public static String getNonce(String content) {
        Blockchain.Transaction transaction = getTransaction(content);
        return transaction.getNonce();
    }

    public static long getQuota(String content) {
        Blockchain.Transaction transaction = getTransaction(content);
        return transaction.getQuota();
    }

    public static String getData(String content) {
        Blockchain.Transaction transaction = getTransaction(content);
        byte[] bDate = transaction.getData().toByteArray();
        return ConvertStrByte.bytesToHexString(bDate);
    }

    public static long getValidUntilBlock(String content) {
        Blockchain.Transaction transaction = getTransaction(content);
        return transaction.getValidUntilBlock();
    }

    public static boolean verifySignature(String addr, String content)
            throws InvalidProtocolBufferException, SignatureException {

        if (!checkAddress(addr)) {
            throw new IllegalArgumentException("Address is not in correct format");
        }

        byte[] contentBytes = ConvertStrByte.hexStringToBytes(Numeric.cleanHexPrefix(content));
        Blockchain.UnverifiedTransaction unverifiedTx
                = Blockchain.UnverifiedTransaction.parseFrom(contentBytes);

        //signature = r (32 byte) + s (32 byte) + v (1 byte)
        ByteString sigByteString = unverifiedTx.getSignature();
        byte[] sigBytes = sigByteString.toByteArray();
        String sig = ConvertStrByte.bytesToHexString(sigBytes);

        if (sig.length() != 130) {
            throw new IllegalArgumentException("Transaction signature is not in correct format");
        }

        String r = sig.substring(0, 64);
        String s = sig.substring(64, 128);
        String v = sig.substring(128);

        byte[] bytesR = ConvertStrByte.hexStringToBytes(r);
        byte[] bytesS = ConvertStrByte.hexStringToBytes(s);
        byte[] bytesV = ConvertStrByte.hexStringToBytes(v);
        byte byteV = bytesV[0];

        String recoveredPubKey = Sign.signedMessageToKey(
                unverifiedTx.getTransaction().toByteArray(),
                new Sign.SignatureData(byteV, bytesR, bytesS)).toString(16);

        String recoveredAddr = Keys.getAddress(recoveredPubKey);

        return recoveredAddr.equals(Numeric.cleanHexPrefix(addr));
    }

    public static Transaction
            decodeContent(String content) throws InvalidProtocolBufferException {

        Blockchain.UnverifiedTransaction unverifiedTx
                = Blockchain.UnverifiedTransaction.parseFrom(
                ConvertStrByte.hexStringToBytes(Numeric.cleanHexPrefix(content)));

        Blockchain.Transaction blockChainTx = unverifiedTx.getTransaction();

        int version = blockChainTx.getVersion();
        String nonce = blockChainTx.getNonce();
        long quota = blockChainTx.getQuota();
        long validUntilBlock = blockChainTx.getValidUntilBlock();
        String data = bytesToHexString(blockChainTx.getData());
        String value = prependHexPrefix(bytesToHexString(blockChainTx.getValue())); // the value-param of Transaction class need add format tag

        String to = null;
        BigInteger chainId = null;

        //version 0: cita 0.19
        //version 1: cita 0.20
        //version 2: cita 0.24
        if (version == 0) {
            to = blockChainTx.getTo();
            chainId = BigInteger.valueOf(blockChainTx.getChainId());
        } else if (version == 1 || version == 2) {
            to = bytesToHexString(blockChainTx.getToV1());
            chainId = Numeric.toBigInt(bytesToHexString(blockChainTx.getChainIdV1()));
        }

        if (chainId == null || to == null) {
            throw new NullPointerException("Cannot get chainId or to from chain.");
        }

        return new Transaction(
                to, nonce, quota, validUntilBlock, version, chainId, value, data);
    }

    private static String bytesToHexString(ByteString byteStr) {
        return ConvertStrByte.bytesToHexString(byteStr.toByteArray());
    }

    public static boolean checkAddress(String addr) {
        return addr.matches("0[xX][0-9a-fA-F]+") && addr.length() == 42;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy