1 package io.bytom.offline.api;
3 import io.bytom.offline.common.DerivePrivateKey;
4 import io.bytom.offline.common.ExpandedPrivateKey;
5 import io.bytom.offline.common.Signer;
6 import io.bytom.offline.common.Utils;
7 import io.bytom.offline.types.*;
8 import io.bytom.offline.util.SHA3Util;
9 import org.bouncycastle.util.encoders.Hex;
10 import java.io.ByteArrayOutputStream;
11 import java.io.IOException;
12 import java.security.SecureRandom;
15 public class IssuanceInput extends BaseInput {
19 private String rawAssetDefinition;
21 public IssuanceInput() {}
23 public IssuanceInput(String assetID, Long amount, String issuanceProgram) {
24 this.setAssetId(assetID);
25 this.setAmount(amount);
26 this.setProgram(issuanceProgram);
29 public IssuanceInput(String assetID, Long amount, String issuanceProgram, String nonce, String rawAssetDefinition) {
30 this(assetID, amount, issuanceProgram);
32 this.rawAssetDefinition = rawAssetDefinition;
36 public InputEntry toInputEntry(Map<Hash, Entry> entryMap, int index) {
37 if (this.nonce == null) {
38 SecureRandom sr = new SecureRandom();
39 byte[] randBytes = new byte[8];
40 sr.nextBytes(randBytes);
41 this.nonce = Hex.toHexString(randBytes);
44 Hash nonceHash = new Hash(SHA3Util.hashSha256(Hex.decode(this.nonce)));
45 Hash assetDefHash = new Hash(this.rawAssetDefinition);
46 AssetAmount value = this.getAssetAmount();
48 Program program = new Program(this.getVmVersion(), Hex.decode(this.getProgram()));
49 return new Issue(nonceHash, value, index, new AssetDefinition(assetDefHash, program));
53 public void buildWitness(String txID) throws Exception {
54 String rootPrivateKey = witnessComponent.getRootPrivateKey();
55 byte[] childPrivateKey = DerivePrivateKey.bip32derivePrvKey(rootPrivateKey, getKeyIndex(), AssetKeySpace);
57 byte[] message = Utils.hashFn(Hex.decode(getInputID()), Hex.decode(txID));
58 byte[] expandedPrivateKey = ExpandedPrivateKey.expandedPrivateKey(childPrivateKey);
59 byte[] sig = Signer.ed25519InnerSign(expandedPrivateKey, message);
61 witnessComponent.appendWitness(Hex.toHexString(sig));
65 public byte[] serializeInputCommitment() throws IOException {
66 ByteArrayOutputStream stream = new ByteArrayOutputStream();
67 Utils.writeVarint(ISSUANCE_INPUT_TYPE, stream);
68 Utils.writeVarStr(Hex.decode(nonce), stream);
69 stream.write(Hex.decode(getAssetId()));
70 Utils.writeVarint(getAmount(), stream);
71 return stream.toByteArray();
75 public byte[] serializeInputWitness() throws IOException {
76 ByteArrayOutputStream stream = new ByteArrayOutputStream();
77 Utils.writeVarStr(Hex.decode(rawAssetDefinition), stream);
79 Utils.writeVarint(1, stream);
80 Utils.writeVarStr(Hex.decode(getProgram()), stream);
81 Utils.writeVarList(witnessComponent.toByteArray(), stream);
86 public void validate() {
89 throw new IllegalArgumentException("the nonce of issuance input must be specified.");
91 if (rawAssetDefinition == null) {
92 throw new IllegalArgumentException("the nonce of issuance input must be specified.");
96 public String getNonce() {
100 public void setNonce(String nonce) {
104 public String getRawAssetDefinition() {
105 return rawAssetDefinition;
108 public void setRawAssetDefinition(String rawAssetDefinition) {
109 this.rawAssetDefinition = rawAssetDefinition;