TRX (wave field) JAVA offline signature

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/qq_18537055/article/details/98681152

Foreword

        In the process of doing an offline wallet, the wave field is data, but most data pits one currency, but also ultimately the successful completion of the development.

data

        https://www.jianshu.com/p/275036a09be3    there are others gathered TRX related information.

Official Demo

        https://github.com/tronprotocol/wallet-cli/blob/master/src/main/java/org/tron/demo/TransactionSignDemo.java

Explanation

        Because we are offline wallet, once we get useless RPC way to block information, is now to get the business end node information in the environmental signature offline, go to broadcast. If the local node or supernode RPC way, then it is the official demo just fine. However, we are direct with the api interface to obtain the data, all out of some problems.
        First constructed https://github.com/tronprotocol/wallet-cli project, after successfully got /build/libs/wallet-1.0-SNAPSHOT.jar, and then open your code journey.

Source

import com.alibaba.fastjson.JSON;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;

import java.util.Map;

import org.bouncycastle.util.encoders.Hex;
import org.tron.common.crypto.ECKey;
import org.tron.common.crypto.Sha256Hash;
import org.tron.common.utils.ByteArray;
import org.tron.core.exception.CancelException;
import org.tron.protos.Contract;
import org.tron.protos.Protocol.Block;
import org.tron.protos.Protocol.Transaction;
import org.tron.walletserver.WalletApi;

public class TransactionSignDemo {

	public static Transaction createTransaction(byte[] from, byte[] to, long amount,long blockTimestamp,long blockHeight,byte[] blockHash) {
		Transaction.Builder transactionBuilder = Transaction.newBuilder();
		//Block newestBlock = WalletApi.getBlock(-1);

		
		Transaction.Contract.Builder contractBuilder = Transaction.Contract.newBuilder();
		Contract.TransferContract.Builder transferContractBuilder = Contract.TransferContract.newBuilder();
		transferContractBuilder.setAmount(amount);
		ByteString bsTo = ByteString.copyFrom(to);
		ByteString bsOwner = ByteString.copyFrom(from);
		transferContractBuilder.setToAddress(bsTo);
		transferContractBuilder.setOwnerAddress(bsOwner);
		try {
			Any any = Any.pack(transferContractBuilder.build());
			contractBuilder.setParameter(any);
		} catch (Exception e) {
			return null;
		}
		contractBuilder.setType(Transaction.Contract.ContractType.TransferContract);
		transactionBuilder.getRawDataBuilder().addContract(contractBuilder).setTimestamp(System.currentTimeMillis())
				.setExpiration(blockTimestamp + 10 * 60 * 60 * 1000);
		Transaction transaction = transactionBuilder.build();
		Transaction refTransaction = setReference(transaction, blockHeight,blockHash);
		return refTransaction;
	}
	
	public static Transaction setReference(Transaction transaction, long blockHeight,byte[] blockHash) {
		//long blockHeight = newestBlock.getBlockHeader().getRawData().getNumber();
		//byte[] blockHash = getBlockHash(newestBlock).getBytes();
		byte[] refBlockNum = ByteArray.fromLong(blockHeight);
		Transaction.raw rawData = transaction.getRawData().toBuilder()
				.setRefBlockHash(ByteString.copyFrom(ByteArray.subArray(blockHash, 8, 16)))
				.setRefBlockBytes(ByteString.copyFrom(ByteArray.subArray(refBlockNum, 6, 8))).build();
		return transaction.toBuilder().setRawData(rawData).build();
	}
	
	public static Sha256Hash getBlockHash(Block block) {
		return Sha256Hash.of(block.getBlockHeader().getRawData().toByteArray());
	}

	public static String getTransactionHash(Transaction transaction) {
		String txid = ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray()));
		return txid;
	}
	private static byte[] signTransaction2Byte(byte[] transaction, byte[] privateKey)
			throws InvalidProtocolBufferException {
		ECKey ecKey = ECKey.fromPrivate(privateKey);
		Transaction transaction1 = Transaction.parseFrom(transaction);
		byte[] rawdata = transaction1.getRawData().toByteArray();
		byte[] hash = Sha256Hash.hash(rawdata);
		byte[] sign = ecKey.sign(hash).toByteArray();
		return transaction1.toBuilder().addSignature(ByteString.copyFrom(sign)).build().toByteArray();
	}

	public static void main(String[] args) throws InvalidProtocolBufferException, CancelException {
		String privateStr = "你的私钥";
		byte[] privateBytes = ByteArray.fromHexString(privateStr);
		ECKey ecKey = ECKey.fromPrivate(privateBytes);
		byte[] from = ecKey.getAddress();
		byte[] to = WalletApi.decodeFromBase58Check("地址");
		long amount = 100_000_000L; 
		
		String blockStr = HttpUtil.get("https://apilist.tronscan.org/api/block/latest");
		Map<String, Object> blockInfo=JSON.parseObject(blockStr);
		System.out.println(blockInfo.toString());
		Long blockTimestamp = Long.parseLong(blockInfo.get("timestamp").toString());
		Long blockHeight = Long.parseLong(blockInfo.get("number").toString());
		
		byte[] blockHash = Hex.decode(blockInfo.get("hash").toString());
		//开始看官方demo改写的blockHashd,但是错的,签名没的问题,但是广播就报错TAPOS_ERROR,说块不在链上。 	
		byte[] blockHash2=Sha256Hash.of(blockInfo.get("hash").toString().getBytes()).getBytes();
		System.out.println("===blockHash:"+ByteArray.toHexString(blockHash));
		System.out.println("===blockHash2:"+ByteArray.toHexString(blockHash2));
		
		Transaction transaction = createTransaction(from, to, amount, blockTimestamp, blockHeight, blockHash);
		byte[] transactionBytes = transaction.toByteArray();
		byte[] transaction4 = signTransaction2Byte(transactionBytes, privateBytes);
		System.out.println("transaction4 ::::: " + ByteArray.toHexString(transaction4));
		
		//广播的URL:https://apilist.tronscan.org/api/broadcast
	}
}

These are our signature demo, the original and changed little, but it was fatal, has been broadcast at the beginning of error: TAPOS_ERROR, looked under the wrong is on the block is not in the chain, but we set and get out all right the block hash value. And there is no source of Block source code, so once I do not know how to solve. Fortunately, later found Hex.decode () method as Transaction.toString byte after the transfer of the print transaction () method for content, then broadcast the results a success.

This is just a demo, as to how to obtain the private key, how to achieve offline, according to their own business scenarios measure of Kazakhstan.

Guess you like

Origin blog.csdn.net/qq_18537055/article/details/98681152