阿希链-1.5版本交易类封装

阿希链于5月份升级版本到1.5,由于阿希公司内部的变动,所以很久没有释放java版本的sdk,我根据1.4.6版本的java版sdk经过修改,完成满足1.5版本的合约交易提交的两个核心类。分别是TransactionBuilder和TransactionInfo。其中TransactionBuilder是对外暴露类,外部提供数据到buildTransaction方法。TransactionInfo内包含阿希相关交易必备的数据,包括签名、二级密码签名等。

下面上代码了,有问题留言!

首先是TransactionInfo.java

package com.asch.xiquspace.AschTools.transaction;

import com.alibaba.fastjson.JSON;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;


public class TransactionInfo {

	public Integer type = null;
	public Integer timestamp = null;
	public Long fee = null;
	public String message = null;
	public Object[] args = null;
	public String senderPublicKey = null;
	public String senderId = null;
	public String[] signatures = null;
	public String secondSignature = null;
	public String id = null;
	
	public byte[] getBytes(boolean skipSignature , boolean skipSignSignature) throws UnsupportedEncodingException {
		ByteBuffer buffer = ByteBuffer.allocate(5120).order(ByteOrder.LITTLE_ENDIAN)
				.putInt(getType().intValue())
				.putInt(getTimestamp().intValue())
				.putLong(getFee().longValue())
				.put(getSenderId().getBytes())
				.put(getMessage().getBytes())
				.put(getArgsBuffer());
		if (!skipSignature && getSignatures() != null) {
			for (String temp : getSignatures()) {
				byte[] buff = hexToByte(temp);
				buffer.put(buff);
			}
		}
		if (!skipSignSignature && getSecondSignature() != null) {
			buffer.put(hexToByte(getSecondSignature()));
		}
		buffer.flip();
		byte[] result = new byte[buffer.remaining()];
		buffer.get(result);

		return result;
	}
	
	
	public byte[] hexToByte(String str) {
	    byte[] bytes = new byte[str.length() / 2];
	    for(int i = 0; i < str.length() / 2; i++) {
	        String subStr = str.substring(i * 2, i * 2 + 2);
	        bytes[i] = (byte) Integer.parseInt(subStr, 16);
	    }
	    return bytes;
	}
	
	
	@Override
	public String toString() {
		return "TransactionInfo [type=" + type + ", timestamp=" + timestamp + ", fee=" + fee + ", message=" + message
				+ ", args=" + Arrays.toString(args) + ", id=" + id + ", senderPublicKey=" + senderPublicKey
				+ ", signature=" + Arrays.toString(signatures) + "]";
	}
	public String getMessage() {
		return message;
	}
	public TransactionInfo setMessage(String message) {
		this.message = message;
		return this;
	}
	public String getSenderId() {
		return senderId;
	}
	public TransactionInfo setSenderId(String senderId) {
		this.senderId = senderId;
		return this;
	}
	public String getSecondSignature() {
		return secondSignature;
	}
	public TransactionInfo setSecondSignature(String secondSignature) {
		this.secondSignature = secondSignature;
		return this;
	}
	public String getId() {
		return id;
	}
	public TransactionInfo setId(String id) {
		this.id = id;
		return this;
	}
	public Long getFee() {
		return fee;
	}
	public TransactionInfo setFee(Long fee) {
		this.fee = fee;
		return this;
	}
	public Integer getTimestamp() {
		return timestamp;
	}
	public TransactionInfo setTimestamp(Integer timestamp) {
		this.timestamp = timestamp;
		return this;
	}
	public String getSenderPublicKey() {
		return senderPublicKey;
	}
	public TransactionInfo setSenderPublicKey(String senderPublicKey) {
		this.senderPublicKey = senderPublicKey;
		return this;
	}
	public Integer getType() {
		return type;
	}
	public TransactionInfo setType(Integer type) {
		this.type = type;
		return this;
	}
	private byte[] getArgsBuffer() {
		return JSON.toJSONString(getArgs()).getBytes();
	}
	public Object[] getArgs() {
		return args;
	}
	public TransactionInfo setArgs(Object[] args) {
		this.args = args;
		return this;
	}
	public String[] getSignatures() {
		return signatures;
	}
	public TransactionInfo setSignature(String[] signature) {
		this.signatures = signature;
		return this;
	}
}
package com.asch.xiquspace.AschTools.transaction;

import com.asch.xiquspace.AschTools.AschBip39;
import so.asch.sdk.codec.Encoding;
import so.asch.sdk.dbc.Argument;
import so.asch.sdk.impl.AschFactory;
import so.asch.sdk.security.Ed25519;
import so.asch.sdk.security.SecurityException;
import so.asch.sdk.security.SecurityStrategy;
import so.asch.sdk.security.ripemd.RipeMD160;

import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;

public class TransactionBuilder {
	private static final String SHA256_DIGEST_ALGORITHM = "SHA-256";

	private static final MessageDigest sha256Digest;
	static {
	
		MessageDigest messageDigest = null;
		RipeMD160 ripeMD160 = null;
		try {
			messageDigest = MessageDigest.getInstance(SHA256_DIGEST_ALGORITHM);
			ripeMD160 = new RipeMD160();
		} catch (Exception ex) {
		}
	
		sha256Digest = messageDigest;
	}
	
	public TransactionInfo buildTransaction(int type, Long fee, Object[] args, String message, String secret, String secondSecret) throws SecurityException {
		KeyPair key = getSecurity().generateKeyPair(secret);
		String publicKey = getPublicKeyString(secret);
		String address = getSecurity().getBase58Address(publicKey);
		TransactionInfo info = newTransaction(key.getPublic(), address, message)
								.setType(type)
								.setArgs(args)
								.setFee(fee);

		return signatureTransaction(info, key.getPrivate(), secondSecret);
	}

	protected TransactionInfo signatureTransaction(TransactionInfo info, PrivateKey privateKey, String secondSecret) {

		try {
			Argument.require(info != null, "transaction can not be null");
			Argument.require(privateKey != null, "private key can not be null");

			byte[] transactionBytes = info.getBytes(true, true);
			
			System.out.println("signBuffer = " + Encoding.hex(transactionBytes));
			
			byte[] hash = sha256Hash(transactionBytes);
			String signture = Encoding.hex(Ed25519.signature(hash, privateKey));
			String[] sings = new String[1];
			sings[0] = signture;
			info.setSignature(sings);
			if(secondSecret != null && !"".equals(secondSecret)) {
				KeyPair secondKeyPair = getSecurity().generateKeyPair(secondSecret);
				byte[] transactionBytes1 = info.getBytes(true, true);
				
				
				byte[] hash1 = sha256Hash(transactionBytes1);
				String signture1 = Encoding.hex(Ed25519.signature(hash1, secondKeyPair.getPrivate()));
				info.setSecondSignature(signture1);
			}
			
			info.setId(generateTransactionId(info));
			
		} catch (Exception ex) {
			try {
				throw new SecurityException("setSignature transaction failed", ex);
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return info;

	}
	
	private String generateTransactionId(TransactionInfo transaction) throws SecurityException {
		try {
            byte[] transactionBytes = transaction.getBytes(false, false);

            
            System.out.println("generateTransactionId = " + Encoding.hex(transactionBytes));
            byte[] hash = sha256Hash(transactionBytes);

            return Encoding.hex(hash);
        } catch (Exception ex) {
            throw new SecurityException("generate transaction id failed", ex);
        }
	}
	
	protected TransactionInfo newTransaction(PublicKey pubKey, String address, String message)
			throws SecurityException, SecurityException {
		String publicKeyHex = getSecurity().encodePublicKey(pubKey);

		return new TransactionInfo()
				.setSenderId(address)
				.setMessage(message)
				.setTimestamp(Integer.valueOf(getSecurity().getTransactionTimestamp()))
				.setSenderPublicKey(publicKeyHex);
	}
	
	private byte[] sha256Hash(byte[] message) {
		sha256Digest.update(message);
		return sha256Digest.digest();
	}
	
	protected SecurityStrategy getSecurity() {
		return AschFactory.getInstance().getSecurity();
	}

	public PublicKey getPublicKey(String secret) {
		SecurityStrategy security = AschFactory.getInstance().getSecurity();
		if (!AschBip39.isValidMnemonicCode(secret)) {
			return null;
		}
		try {
			return security.generateKeyPair(secret).getPublic();
		} catch (Exception ex) {
		}
		return null;
	}

	public String getPublicKeyString(String secret) {
		SecurityStrategy security = AschFactory.getInstance().getSecurity();
		if (!AschBip39.isValidMnemonicCode(secret)) {
			return null;
		}
		try {
			return security.encodePublicKey(security.generateKeyPair(secret).getPublic());
		} catch (Exception ex) {
		}
		return null;
	}

}

 

调用方法如下:

TransactionInfo info = new TransactionBuilder().buildTransaction(type, fee, args, message, secret, secondSecret);
                ParameterMap map = new ParameterMap();
            map.put("transaction", info);

            Map mapHeader = new HashMap<>();
            mapHeader.put("magic", magic);
            mapHeader.put("Content-Type", "application/json");
            String url = AschConfig.aschServerUrl + "/peer/transactions";

            HttpREST.postJsonContent(url, map.toJSONString(), mapHeader, mHandler);

 其中AschConfig.aschServerUrl是阿希主网的链接或者自己测试网络的链接,组装完成数据之后,则通过Http post到主网内完成交易!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值