Official Java SDK for Bytom
Révision | 44fc5c26e55aefe6f5647f5d637903b060b52a92 (tree) |
---|---|
l'heure | 2021-07-13 18:42:14 |
Auteur | doraemon <wyjDoraemon@163....> |
Commiter | doraemon |
offine signer
@@ -11,6 +11,8 @@ public abstract class BaseInput { | ||
11 | 11 | |
12 | 12 | static final int ISSUANCE_INPUT_TYPE = 0; |
13 | 13 | static final int SPEND_INPUT_TYPE = 1; |
14 | + static final int Coinbase_INPUT_TYPE = 2; | |
15 | + static final int Veto_INPUT_TYPE = 3; | |
14 | 16 | |
15 | 17 | static final byte AssetKeySpace = 0; |
16 | 18 | static final byte AccountKeySpace = 1; |
@@ -52,7 +54,7 @@ public abstract class BaseInput { | ||
52 | 54 | |
53 | 55 | public byte[] serializeInput() throws IOException { |
54 | 56 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
55 | - // assert version | |
57 | + // asset version | |
56 | 58 | Utils.writeVarint(1, stream); |
57 | 59 | Utils.writeExtensibleString(serializeInputCommitment(), stream); |
58 | 60 | Utils.writeExtensibleString(serializeInputWitness(), stream); |
@@ -133,4 +135,8 @@ public abstract class BaseInput { | ||
133 | 135 | public void setKeyIndex(int keyIndex) { |
134 | 136 | this.keyIndex = keyIndex; |
135 | 137 | } |
138 | + | |
139 | + public void appendWitnessComponent(String witness){ | |
140 | + witnessComponent.appendWitness(witness); | |
141 | + } | |
136 | 142 | } |
@@ -0,0 +1,55 @@ | ||
1 | +package io.bytom.offline.api; | |
2 | + | |
3 | +import io.bytom.offline.common.Utils; | |
4 | +import io.bytom.offline.types.*; | |
5 | +import org.bouncycastle.util.encoders.Hex; | |
6 | + | |
7 | +import java.io.ByteArrayOutputStream; | |
8 | +import java.io.IOException; | |
9 | +import java.util.Map; | |
10 | + | |
11 | +public abstract class BaseOutput { | |
12 | + /** | |
13 | + * The number of units of the asset being controlled. | |
14 | + */ | |
15 | + private Long amount; | |
16 | + | |
17 | + /** | |
18 | + * The id of the asset being controlled. | |
19 | + */ | |
20 | + private String assetId; | |
21 | + | |
22 | + /** | |
23 | + * The control program which must be satisfied to transfer this output. | |
24 | + */ | |
25 | + private String controlProgram; | |
26 | + | |
27 | + /** | |
28 | + * The id of the output. | |
29 | + */ | |
30 | + private String id; | |
31 | + | |
32 | + StateData stateData = new StateData(); | |
33 | + | |
34 | + public BaseOutput() { | |
35 | + } | |
36 | + | |
37 | + public BaseOutput(String assetID, long amount, String controlProgram) { | |
38 | + this.assetId = assetID; | |
39 | + this.amount = amount; | |
40 | + this.controlProgram = controlProgram; | |
41 | + } | |
42 | + | |
43 | + | |
44 | + public abstract byte[] serializeOutputCommitment() throws IOException; | |
45 | + | |
46 | + | |
47 | + public byte[] serializeOutput() throws IOException { | |
48 | + ByteArrayOutputStream stream = new ByteArrayOutputStream(); | |
49 | + // asset version | |
50 | + Utils.writeVarint(1, stream); | |
51 | + Utils.writeExtensibleString(serializeOutputCommitment(), stream); | |
52 | + return stream.toByteArray(); | |
53 | + } | |
54 | + | |
55 | +} | |
\ No newline at end of file |
@@ -0,0 +1,48 @@ | ||
1 | +package io.bytom.offline.api; | |
2 | + | |
3 | +import io.bytom.offline.common.Utils; | |
4 | +import io.bytom.offline.types.*; | |
5 | +import org.bouncycastle.util.encoders.Hex; | |
6 | + | |
7 | +import java.io.ByteArrayOutputStream; | |
8 | +import java.io.IOException; | |
9 | +import java.util.Map; | |
10 | + | |
11 | +public class CoinbaseInput extends BaseInput{ | |
12 | + private String arbitrary; | |
13 | + | |
14 | + @Override | |
15 | + public InputEntry toInputEntry(Map<Hash, Entry> entryMap, int index) { | |
16 | + Coinbase coinbase = new Coinbase(arbitrary); | |
17 | + | |
18 | + Hash prevOutID = coinbase.entryID(); | |
19 | + entryMap.put(prevOutID, coinbase); | |
20 | + return new Coinbase(prevOutID,index); | |
21 | + } | |
22 | + | |
23 | + @Override | |
24 | + public void buildWitness(String txID) throws Exception { | |
25 | + | |
26 | + } | |
27 | + | |
28 | + @Override | |
29 | + public byte[] serializeInputCommitment() throws IOException { | |
30 | + ByteArrayOutputStream stream = new ByteArrayOutputStream(); | |
31 | + Utils.writeVarint(Coinbase_INPUT_TYPE, stream); | |
32 | + Utils.writeVarStr(Hex.decode(this.arbitrary),stream); | |
33 | + return stream.toByteArray(); | |
34 | + } | |
35 | + | |
36 | + @Override | |
37 | + public byte[] serializeInputWitness() throws IOException { | |
38 | + return new byte[0]; | |
39 | + } | |
40 | + | |
41 | + public String getArbitrary() { | |
42 | + return arbitrary; | |
43 | + } | |
44 | + | |
45 | + public void setArbitrary(String arbitrary) { | |
46 | + this.arbitrary = arbitrary; | |
47 | + } | |
48 | +} |
@@ -5,6 +5,7 @@ import io.bytom.offline.common.ExpandedPrivateKey; | ||
5 | 5 | import io.bytom.offline.common.Signer; |
6 | 6 | import io.bytom.offline.common.Utils; |
7 | 7 | import io.bytom.offline.types.*; |
8 | +import io.bytom.offline.util.AssetIdUtil; | |
8 | 9 | import io.bytom.offline.util.SHA3Util; |
9 | 10 | import org.bouncycastle.util.encoders.Hex; |
10 | 11 | import java.io.ByteArrayOutputStream; |
@@ -18,7 +19,15 @@ public class IssuanceInput extends BaseInput { | ||
18 | 19 | |
19 | 20 | private String rawAssetDefinition; |
20 | 21 | |
21 | - public IssuanceInput() {} | |
22 | + public IssuanceInput(){ | |
23 | + | |
24 | + } | |
25 | + | |
26 | + public IssuanceInput(String rawAssetDefinition,String issuanceProgram) { | |
27 | + this.rawAssetDefinition = rawAssetDefinition; | |
28 | + this.setProgram(issuanceProgram); | |
29 | + this.setAssetId(AssetIdUtil.computeAssetID(rawAssetDefinition,issuanceProgram)); | |
30 | + } | |
22 | 31 | |
23 | 32 | public IssuanceInput(String assetID, Long amount, String issuanceProgram) { |
24 | 33 | this.setAssetId(assetID); |
@@ -66,7 +75,10 @@ public class IssuanceInput extends BaseInput { | ||
66 | 75 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
67 | 76 | Utils.writeVarint(ISSUANCE_INPUT_TYPE, stream); |
68 | 77 | Utils.writeVarStr(Hex.decode(nonce), stream); |
69 | - stream.write(Hex.decode(getAssetId())); | |
78 | + if (this.getAssetId()==null){ | |
79 | + this.setAssetId(AssetIdUtil.computeAssetID(rawAssetDefinition,this.getProgram())); | |
80 | + } | |
81 | + stream.write(Hex.decode(this.getAssetId())); | |
70 | 82 | Utils.writeVarint(getAmount(), stream); |
71 | 83 | return stream.toByteArray(); |
72 | 84 | } |
@@ -84,13 +96,16 @@ public class IssuanceInput extends BaseInput { | ||
84 | 96 | |
85 | 97 | @Override |
86 | 98 | public void validate() { |
87 | - super.validate(); | |
88 | 99 | if (nonce == null) { |
89 | 100 | throw new IllegalArgumentException("the nonce of issuance input must be specified."); |
90 | 101 | } |
91 | 102 | if (rawAssetDefinition == null) { |
92 | 103 | throw new IllegalArgumentException("the nonce of issuance input must be specified."); |
93 | 104 | } |
105 | + | |
106 | + if (this.getProgram() == null) { | |
107 | + throw new IllegalArgumentException("the program of issuance must be specified."); | |
108 | + } | |
94 | 109 | } |
95 | 110 | |
96 | 111 | public String getNonce() { |
@@ -2,12 +2,12 @@ package io.bytom.offline.api; | ||
2 | 2 | |
3 | 3 | import io.bytom.offline.common.Utils; |
4 | 4 | import io.bytom.offline.common.VMUtil; |
5 | +import io.bytom.offline.util.AssetIdUtil; | |
5 | 6 | import org.bouncycastle.util.encoders.Hex; |
6 | 7 | import java.io.ByteArrayOutputStream; |
7 | 8 | import java.io.IOException; |
8 | 9 | |
9 | -public class Output { | |
10 | - | |
10 | +public class OriginalOutput { | |
11 | 11 | /** |
12 | 12 | * The number of units of the asset being controlled. |
13 | 13 | */ |
@@ -28,27 +28,28 @@ public class Output { | ||
28 | 28 | */ |
29 | 29 | private String id; |
30 | 30 | |
31 | - /** | |
32 | - * The output's position in a transaction's list of outputs. | |
33 | - */ | |
34 | - private Integer position; | |
31 | + StateData stateData = new StateData(); | |
32 | + | |
33 | + public OriginalOutput() { | |
34 | + } | |
35 | 35 | |
36 | - public Output(String assetID, long amount, String controlProgram) { | |
36 | + public OriginalOutput(String assetID, long amount, String controlProgram) { | |
37 | 37 | this.assetId = assetID; |
38 | 38 | this.amount = amount; |
39 | 39 | this.controlProgram = controlProgram; |
40 | 40 | } |
41 | 41 | |
42 | - public static Output newRetireOutput(String assetID, long amount, String arbitrary) { | |
43 | - String retireProgram = Hex.toHexString(new byte[]{VMUtil.OP_FAIL}) + Hex.toHexString(VMUtil.pushDataBytes(Hex.decode(arbitrary))); | |
44 | - return new Output(assetID, amount, retireProgram); | |
42 | + public OriginalOutput(String rawAssetDefinition,String program) { | |
43 | + this.assetId = AssetIdUtil.computeAssetID(rawAssetDefinition,program); | |
44 | + this.controlProgram = program; | |
45 | 45 | } |
46 | 46 | |
47 | 47 | public byte[] serializeOutput() throws IOException { |
48 | 48 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
49 | - | |
50 | - //assetVersion | |
51 | - Utils.writeVarint(1, stream); //AssetVersion是否默认为1 | |
49 | + // asset version | |
50 | + Utils.writeVarint(1, stream); | |
51 | + //outputType | |
52 | + Utils.writeVarint(0, stream); //outputType | |
52 | 53 | //outputCommit |
53 | 54 | ByteArrayOutputStream outputCommitSteam = new ByteArrayOutputStream(); |
54 | 55 | //assetId |
@@ -59,6 +60,8 @@ public class Output { | ||
59 | 60 | Utils.writeVarint(1, outputCommitSteam); //db中获取vm_version |
60 | 61 | //controlProgram |
61 | 62 | Utils.writeVarStr(Hex.decode(controlProgram), outputCommitSteam); |
63 | + //stateData | |
64 | + Utils.writeVarList(this.stateData.toByteArray(), outputCommitSteam); | |
62 | 65 | |
63 | 66 | Utils.writeExtensibleString(outputCommitSteam.toByteArray(), stream); |
64 | 67 |
@@ -67,6 +70,7 @@ public class Output { | ||
67 | 70 | return stream.toByteArray(); |
68 | 71 | } |
69 | 72 | |
73 | + | |
70 | 74 | public Long getAmount() { |
71 | 75 | return amount; |
72 | 76 | } |
@@ -99,11 +103,7 @@ public class Output { | ||
99 | 103 | this.id = id; |
100 | 104 | } |
101 | 105 | |
102 | - public Integer getPosition() { | |
103 | - return position; | |
104 | - } | |
105 | - | |
106 | - public void setPosition(Integer position) { | |
107 | - this.position = position; | |
106 | + public void appendStateData(String stateDataStr){ | |
107 | + stateData.appendStateData(stateDataStr); | |
108 | 108 | } |
109 | 109 | } |
@@ -19,6 +19,8 @@ public class SpendInput extends BaseInput { | ||
19 | 19 | |
20 | 20 | private BIPProtocol bipProtocol = BIPProtocol.BIP44; |
21 | 21 | |
22 | + StateData stateData = new StateData(); | |
23 | + | |
22 | 24 | public SpendInput() {} |
23 | 25 | |
24 | 26 | public SpendInput(String assetID, long amount, String controlProgram) { |
@@ -40,7 +42,7 @@ public class SpendInput extends BaseInput { | ||
40 | 42 | Hash sourceID = new Hash(this.sourceID); |
41 | 43 | ValueSource src = new ValueSource(sourceID, assetAmount, this.sourcePosition); |
42 | 44 | |
43 | - OutputEntry prevOut = new OutputEntry(src, pro, 0); | |
45 | + Output prevOut = new Output(src, pro, 0,stateData.toByteArray()); | |
44 | 46 | Hash prevOutID = prevOut.entryID(); |
45 | 47 | entryMap.put(prevOutID, prevOut); |
46 | 48 | return new Spend(prevOutID, index); |
@@ -82,6 +84,7 @@ public class SpendInput extends BaseInput { | ||
82 | 84 | // vm version |
83 | 85 | Utils.writeVarint(1, spendCommitSteam); |
84 | 86 | Utils.writeVarStr(Hex.decode(getProgram()), spendCommitSteam); |
87 | + Utils.writeVarList(stateData.toByteArray(), spendCommitSteam); | |
85 | 88 | Utils.writeExtensibleString(spendCommitSteam.toByteArray(), stream); |
86 | 89 | return stream.toByteArray(); |
87 | 90 | } |
@@ -129,4 +132,8 @@ public class SpendInput extends BaseInput { | ||
129 | 132 | public void setBipProtocol(BIPProtocol bipProtocol) { |
130 | 133 | this.bipProtocol = bipProtocol; |
131 | 134 | } |
135 | + | |
136 | + public void appendStateData(String stateDataStr){ | |
137 | + stateData.appendStateData(stateDataStr); | |
138 | + } | |
132 | 139 | } |
\ No newline at end of file |
@@ -0,0 +1,26 @@ | ||
1 | +package io.bytom.offline.api; | |
2 | + | |
3 | +import org.bouncycastle.util.encoders.Hex; | |
4 | + | |
5 | +import java.util.ArrayList; | |
6 | +import java.util.List; | |
7 | + | |
8 | +public class StateData { | |
9 | + private List<String> stateData; | |
10 | + | |
11 | + public StateData() { | |
12 | + stateData = new ArrayList<>(); | |
13 | + } | |
14 | + | |
15 | + public byte[][] toByteArray() { | |
16 | + byte[][] byteArray = new byte[stateData.size()][]; | |
17 | + for (int i = 0; i < stateData.size(); i++) { | |
18 | + byteArray[i] = Hex.decode(stateData.get(i)); | |
19 | + } | |
20 | + return byteArray; | |
21 | + } | |
22 | + | |
23 | + public void appendStateData(String stateDataStr) { | |
24 | + stateData.add(stateDataStr); | |
25 | + } | |
26 | +} |
@@ -41,7 +41,7 @@ public class Transaction { | ||
41 | 41 | /** |
42 | 42 | * List of specified outputs for a transaction. |
43 | 43 | */ |
44 | - private List<Output> outputs; | |
44 | + private List<OriginalOutput> outputs; | |
45 | 45 | |
46 | 46 | public Transaction(Builder builder) { |
47 | 47 | this.inputs = builder.inputs; |
@@ -64,7 +64,7 @@ public class Transaction { | ||
64 | 64 | private Integer timeRange; |
65 | 65 | |
66 | 66 | private List<BaseInput> inputs; |
67 | - private List<Output> outputs; | |
67 | + private List<OriginalOutput> outputs; | |
68 | 68 | |
69 | 69 | public Builder() { |
70 | 70 | this.inputs = new ArrayList<>(); |
@@ -76,7 +76,7 @@ public class Transaction { | ||
76 | 76 | return this; |
77 | 77 | } |
78 | 78 | |
79 | - public Builder addOutput(Output output) { | |
79 | + public Builder addOutput(OriginalOutput output) { | |
80 | 80 | this.outputs.add(output); |
81 | 81 | return this; |
82 | 82 | } |
@@ -86,12 +86,17 @@ public class Transaction { | ||
86 | 86 | return this; |
87 | 87 | } |
88 | 88 | |
89 | + public Builder setSize(int size) { | |
90 | + this.size = size; | |
91 | + return this; | |
92 | + } | |
93 | + | |
89 | 94 | public Transaction build() { |
90 | 95 | return new Transaction(this); |
91 | 96 | } |
92 | 97 | } |
93 | 98 | |
94 | - private void sign() { | |
99 | + public void sign() { | |
95 | 100 | for (BaseInput input : inputs) { |
96 | 101 | try { |
97 | 102 | input.buildWitness(txID); |
@@ -117,7 +122,7 @@ public class Transaction { | ||
117 | 122 | } |
118 | 123 | |
119 | 124 | Utils.writeVarint(outputs.size(), stream); |
120 | - for (Output output : outputs) { | |
125 | + for (OriginalOutput output : outputs) { | |
121 | 126 | stream.write(output.serializeOutput()); |
122 | 127 | } |
123 | 128 | } catch (IOException e) { |
@@ -167,7 +172,7 @@ public class Transaction { | ||
167 | 172 | |
168 | 173 | List<Hash> resultIDList = new ArrayList<>(); |
169 | 174 | for (int i = 0; i < outputs.size(); i++) { |
170 | - Output output = outputs.get(i); | |
175 | + OriginalOutput output = outputs.get(i); | |
171 | 176 | |
172 | 177 | AssetAmount amount = new AssetAmount(new AssetID(output.getAssetId()), output.getAmount()); |
173 | 178 | ValueSource src = new ValueSource(muxID, amount, i); |
@@ -178,7 +183,7 @@ public class Transaction { | ||
178 | 183 | resultID = addEntry(entryMap, retirement); |
179 | 184 | } else { |
180 | 185 | Program program = new Program(1, Hex.decode(output.getControlProgram())); |
181 | - OutputEntry oup = new OutputEntry(src, program, i); | |
186 | + Output oup = new Output(src, program, i,output.stateData.toByteArray()); | |
182 | 187 | resultID = addEntry(entryMap, oup); |
183 | 188 | } |
184 | 189 |
@@ -225,7 +230,7 @@ public class Transaction { | ||
225 | 230 | return inputs; |
226 | 231 | } |
227 | 232 | |
228 | - public List<Output> getOutputs() { | |
233 | + public List<OriginalOutput> getOutputs() { | |
229 | 234 | return outputs; |
230 | 235 | } |
231 | 236 | } |
@@ -0,0 +1,108 @@ | ||
1 | +package io.bytom.offline.api; | |
2 | + | |
3 | +import io.bytom.offline.common.Utils; | |
4 | +import io.bytom.offline.types.*; | |
5 | +import org.bouncycastle.util.encoders.Hex; | |
6 | + | |
7 | +import java.io.ByteArrayOutputStream; | |
8 | +import java.io.IOException; | |
9 | +import java.util.Map; | |
10 | + | |
11 | +public class VetoInput extends BaseInput{ | |
12 | + private String sourceID; | |
13 | + | |
14 | + private Integer sourcePosition; | |
15 | + | |
16 | + private Boolean change; | |
17 | + | |
18 | + private Integer controlProgramIndex; | |
19 | + | |
20 | + private byte[] vote; | |
21 | + | |
22 | + StateData stateData = new StateData(); | |
23 | + | |
24 | + @Override | |
25 | + public InputEntry toInputEntry(Map<Hash, Entry> entryMap, int index) { | |
26 | + Program pro = new Program(this.getVmVersion(), Hex.decode(this.getProgram())); | |
27 | + AssetAmount assetAmount = this.getAssetAmount(); | |
28 | + Hash sourceID = new Hash(this.sourceID); | |
29 | + ValueSource src = new ValueSource(sourceID, assetAmount, this.sourcePosition); | |
30 | + | |
31 | + Vote prevOut = new Vote(src, pro, 0,this.vote,stateData.toByteArray()); | |
32 | + Hash prevOutID = prevOut.entryID(); | |
33 | + entryMap.put(prevOutID, prevOut); | |
34 | + return new Veto(prevOutID, index); | |
35 | + } | |
36 | + | |
37 | + @Override | |
38 | + public void buildWitness(String txID) throws Exception { | |
39 | + | |
40 | + } | |
41 | + | |
42 | + @Override | |
43 | + public byte[] serializeInputCommitment() throws IOException { | |
44 | + ByteArrayOutputStream stream = new ByteArrayOutputStream(); | |
45 | + Utils.writeVarint(Veto_INPUT_TYPE, stream); | |
46 | + | |
47 | + ByteArrayOutputStream spendCommitSteam = new ByteArrayOutputStream(); | |
48 | + spendCommitSteam.write(Hex.decode(sourceID)); | |
49 | + spendCommitSteam.write(Hex.decode(getAssetId())); | |
50 | + Utils.writeVarint(getAmount(), spendCommitSteam); | |
51 | + Utils.writeVarint(sourcePosition, spendCommitSteam); | |
52 | + // vm version | |
53 | + Utils.writeVarint(1, spendCommitSteam); | |
54 | + Utils.writeVarStr(Hex.decode(getProgram()), spendCommitSteam); | |
55 | + Utils.writeVarList(stateData.toByteArray(), spendCommitSteam); | |
56 | + Utils.writeExtensibleString(spendCommitSteam.toByteArray(), stream); | |
57 | + Utils.writeVarStr(this.vote,stream); | |
58 | + return stream.toByteArray(); | |
59 | + } | |
60 | + | |
61 | + @Override | |
62 | + public byte[] serializeInputWitness() throws IOException { | |
63 | + ByteArrayOutputStream stream = new ByteArrayOutputStream(); | |
64 | + Utils.writeVarList(witnessComponent.toByteArray(), stream); | |
65 | + return stream.toByteArray(); | |
66 | + } | |
67 | + | |
68 | + public String getSourceID() { | |
69 | + return sourceID; | |
70 | + } | |
71 | + | |
72 | + public void setSourceID(String sourceID) { | |
73 | + this.sourceID = sourceID; | |
74 | + } | |
75 | + | |
76 | + public Integer getSourcePosition() { | |
77 | + return sourcePosition; | |
78 | + } | |
79 | + | |
80 | + public void setSourcePosition(Integer sourcePosition) { | |
81 | + this.sourcePosition = sourcePosition; | |
82 | + } | |
83 | + | |
84 | + public Boolean getChange() { | |
85 | + return change; | |
86 | + } | |
87 | + | |
88 | + public void setChange(Boolean change) { | |
89 | + this.change = change; | |
90 | + } | |
91 | + | |
92 | + public Integer getControlProgramIndex() { | |
93 | + return controlProgramIndex; | |
94 | + } | |
95 | + | |
96 | + public void setControlProgramIndex(Integer controlProgramIndex) { | |
97 | + this.controlProgramIndex = controlProgramIndex; | |
98 | + } | |
99 | + | |
100 | + public byte[] getVote() { | |
101 | + return vote; | |
102 | + } | |
103 | + | |
104 | + public void setVote(byte[] vote) { | |
105 | + this.vote = vote; | |
106 | + } | |
107 | + | |
108 | +} |
@@ -0,0 +1,50 @@ | ||
1 | +package io.bytom.offline.types; | |
2 | + | |
3 | +import java.io.ByteArrayOutputStream; | |
4 | +import java.util.Map; | |
5 | + | |
6 | +public class Coinbase extends InputEntry{ | |
7 | + private Hash coinbaseOutputID; | |
8 | + | |
9 | + private int ordinal; | |
10 | + | |
11 | + private ValueDestination witnessDestination; | |
12 | + | |
13 | + private String arbitrary; | |
14 | + | |
15 | + public Coinbase(Hash coinbaseOutputID, int ordinal) { | |
16 | + this.coinbaseOutputID = coinbaseOutputID; | |
17 | + this.ordinal = ordinal; | |
18 | + } | |
19 | + | |
20 | + public Coinbase(String arbitrary) { | |
21 | + this.arbitrary = arbitrary; | |
22 | + } | |
23 | + | |
24 | + | |
25 | + @Override | |
26 | + public String typ() { | |
27 | + return "coinbase1"; | |
28 | + } | |
29 | + | |
30 | + @Override | |
31 | + public void writeForHash(ByteArrayOutputStream out) { | |
32 | + System.out.println("write for hash"); | |
33 | + System.out.println(this.arbitrary); | |
34 | + mustWriteForHash(out,this.arbitrary); | |
35 | + } | |
36 | + | |
37 | + @Override | |
38 | + public void setDestination(Hash id, long pos, Map<Hash, Entry> entryMap) { | |
39 | +// OutputEntry spendOutput = (OutputEntry) entryMap.get(this.coinbaseOutputID); | |
40 | +// this.witnessDestination = new ValueDestination(id, spendOutput.getSource().getValue(), pos); | |
41 | + } | |
42 | + | |
43 | + public String getArbitrary() { | |
44 | + return arbitrary; | |
45 | + } | |
46 | + | |
47 | + public void setArbitrary(String arbitrary) { | |
48 | + this.arbitrary = arbitrary; | |
49 | + } | |
50 | +} |
@@ -0,0 +1,30 @@ | ||
1 | +package io.bytom.offline.types; | |
2 | + | |
3 | +import java.io.ByteArrayOutputStream; | |
4 | + | |
5 | +public class Output extends OutputEntry { | |
6 | + public Output() { | |
7 | + this.source = new ValueSource(); | |
8 | + this.controlProgram = new Program(); | |
9 | + } | |
10 | + | |
11 | + | |
12 | + public Output(ValueSource source, Program controlProgram, Integer ordinal, byte[][] stateData) { | |
13 | + this.source = source; | |
14 | + this.controlProgram = controlProgram; | |
15 | + this.ordinal = ordinal; | |
16 | + this.stateData = stateData; | |
17 | + } | |
18 | + | |
19 | + @Override | |
20 | + public String typ() { | |
21 | + return "originalOutput1"; | |
22 | + } | |
23 | + | |
24 | + @Override | |
25 | + public void writeForHash(ByteArrayOutputStream out) { | |
26 | + mustWriteForHash(out, this.source); | |
27 | + mustWriteForHash(out, this.controlProgram); | |
28 | + mustWriteForHash(out, this.stateData); | |
29 | + } | |
30 | +} |
@@ -2,36 +2,15 @@ package io.bytom.offline.types; | ||
2 | 2 | |
3 | 3 | import java.io.ByteArrayOutputStream; |
4 | 4 | |
5 | -public class OutputEntry extends Entry { | |
5 | +public abstract class OutputEntry extends Entry { | |
6 | + protected ValueSource source; | |
6 | 7 | |
7 | - private ValueSource source; | |
8 | + protected Program controlProgram; | |
8 | 9 | |
9 | - private Program controlProgram; | |
10 | + protected Integer ordinal; | |
10 | 11 | |
11 | - private Integer ordinal; | |
12 | + protected byte[][] stateData; | |
12 | 13 | |
13 | - public OutputEntry() { | |
14 | - this.source = new ValueSource(); | |
15 | - this.controlProgram = new Program(); | |
16 | - } | |
17 | - | |
18 | - | |
19 | - public OutputEntry(ValueSource source, Program controlProgram, Integer ordinal) { | |
20 | - this.source = source; | |
21 | - this.controlProgram = controlProgram; | |
22 | - this.ordinal = ordinal; | |
23 | - } | |
24 | - | |
25 | - @Override | |
26 | - public String typ() { | |
27 | - return "output1"; | |
28 | - } | |
29 | - | |
30 | - @Override | |
31 | - public void writeForHash(ByteArrayOutputStream out) { | |
32 | - mustWriteForHash(out, this.source); | |
33 | - mustWriteForHash(out, this.controlProgram); | |
34 | - } | |
35 | 14 | |
36 | 15 | public ValueSource getSource() { |
37 | 16 | return source; |
@@ -11,12 +11,18 @@ public class ValueSource { | ||
11 | 11 | |
12 | 12 | public ValueSource() {} |
13 | 13 | |
14 | + public ValueSource(Hash ref, AssetAmount value) { | |
15 | + this.ref = ref; | |
16 | + this.value = value; | |
17 | + } | |
18 | + | |
14 | 19 | public ValueSource(Hash ref, AssetAmount value, long position) { |
15 | 20 | this.ref = ref; |
16 | 21 | this.value = value; |
17 | 22 | this.position = position; |
18 | 23 | } |
19 | 24 | |
25 | + | |
20 | 26 | public Hash getRef() { |
21 | 27 | return ref; |
22 | 28 | } |
@@ -0,0 +1,31 @@ | ||
1 | +package io.bytom.offline.types; | |
2 | + | |
3 | +import java.io.ByteArrayOutputStream; | |
4 | +import java.util.Map; | |
5 | + | |
6 | +public class Veto extends InputEntry{ | |
7 | + private Hash spentOutputID; | |
8 | + private ValueDestination witnessDestination; | |
9 | + | |
10 | + | |
11 | + public Veto(Hash spentOutputID, int ordinal) { | |
12 | + this.spentOutputID = spentOutputID; | |
13 | + this.ordinal = ordinal; | |
14 | + } | |
15 | + | |
16 | + @Override | |
17 | + public String typ() { | |
18 | + return "vetoInput1"; | |
19 | + } | |
20 | + | |
21 | + @Override | |
22 | + public void writeForHash(ByteArrayOutputStream out) { | |
23 | + mustWriteForHash(out,this.spentOutputID); | |
24 | + } | |
25 | + | |
26 | + @Override | |
27 | + public void setDestination(Hash id, long pos, Map<Hash, Entry> entryMap) { | |
28 | + OutputEntry spendOutput = (OutputEntry) entryMap.get(this.spentOutputID); | |
29 | + this.witnessDestination = new ValueDestination(id, spendOutput.getSource().getValue(), pos); | |
30 | + } | |
31 | +} |
@@ -0,0 +1,37 @@ | ||
1 | +package io.bytom.offline.types; | |
2 | + | |
3 | +import java.io.ByteArrayOutputStream; | |
4 | + | |
5 | +public class Vote extends OutputEntry{ | |
6 | + private byte[] vote; | |
7 | + | |
8 | + public Vote(ValueSource source, Program controlProgram, Integer ordinal,byte[] vote, byte[][] stateData) { | |
9 | + this.source = source; | |
10 | + this.controlProgram = controlProgram; | |
11 | + this.ordinal = ordinal; | |
12 | + this.vote = vote; | |
13 | + this.stateData = stateData; | |
14 | + } | |
15 | + | |
16 | + @Override | |
17 | + public String typ() { | |
18 | + return "voteOutput1"; | |
19 | + } | |
20 | + | |
21 | + @Override | |
22 | + public void writeForHash(ByteArrayOutputStream out) { | |
23 | + mustWriteForHash(out,this.source); | |
24 | + mustWriteForHash(out,this.controlProgram); | |
25 | + mustWriteForHash(out,this.vote); | |
26 | + mustWriteForHash(out,this.stateData); | |
27 | + } | |
28 | + | |
29 | + public byte[] getVote() { | |
30 | + return vote; | |
31 | + } | |
32 | + | |
33 | + public void setVote(byte[] vote) { | |
34 | + this.vote = vote; | |
35 | + } | |
36 | + | |
37 | +} |
@@ -0,0 +1,20 @@ | ||
1 | +package io.bytom.offline.util; | |
2 | + | |
3 | +import io.bytom.offline.types.AssetDefinition; | |
4 | +import io.bytom.offline.types.Hash; | |
5 | +import io.bytom.offline.types.Program; | |
6 | +import org.bouncycastle.util.encoders.Hex; | |
7 | + | |
8 | +import java.io.ByteArrayOutputStream; | |
9 | + | |
10 | +public class AssetIdUtil { | |
11 | + public static String computeAssetID(String rawAssetDefinition,String controlProgram){ | |
12 | + byte[] hashBytes = SHA3Util.hashSha256(Hex.decode(rawAssetDefinition)); | |
13 | + Hash assetDefHash = new Hash(hashBytes); | |
14 | + Program program = new Program(1,Hex.decode(controlProgram)); | |
15 | + AssetDefinition assetDefinition = new AssetDefinition(assetDefHash, program); | |
16 | + ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
17 | + assetDefinition.writeForHash(out); | |
18 | + return Hex.toHexString(SHA3Util.hashSha256(out.toByteArray())); | |
19 | + } | |
20 | +} |
@@ -1,128 +0,0 @@ | ||
1 | -package io.bytom.offline.api; | |
2 | - | |
3 | -import org.junit.Test; | |
4 | - | |
5 | -public class AppTest { | |
6 | - String rootKey = "38d2c44314c401b3ea7c23c54e12c36a527aee46a7f26b82443a46bf40583e439dea25de09b0018b35a741d8cd9f6ec06bc11db49762617485f5309ab72a12d4"; | |
7 | - String btmAssetID = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; | |
8 | - | |
9 | - | |
10 | - @Test | |
11 | - public void testSpendBIP44() { | |
12 | - SpendInput input = new SpendInput(); | |
13 | - input.setAssetId(btmAssetID); | |
14 | - input.setAmount(9800000000L); | |
15 | - input.setProgram("0014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e"); | |
16 | - input.setSourcePosition(2); | |
17 | - input.setSourceID("4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea"); | |
18 | - input.setChange(true); | |
19 | - input.setControlProgramIndex(457); | |
20 | - input.setKeyIndex(1); | |
21 | - input.setRootPrivateKey("4864bae85cf38bfbb347684abdbc01e311a24f99e2c7fe94f3c071d9c83d8a5a349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257"); | |
22 | - | |
23 | - Transaction tx = new Transaction.Builder() | |
24 | - .addInput(input) | |
25 | - .addOutput(new Output(btmAssetID, 8800000000L, "0014a82f02bc37bc5ed87d5f9fca02f8a6a7d89cdd5c")) | |
26 | - .addOutput(new Output(btmAssetID, 900000000L, "00200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66")) | |
27 | - .setTimeRange(0) | |
28 | - .build(); | |
29 | - | |
30 | - String rawTransaction = tx.rawTransaction(); | |
31 | - assert rawTransaction.equals("070100010160015e4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c480c1240201160014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e6302401cb779288be890a28c5209036da1a27d9fe74a51c38e0a10db4817bcf4fd05f68580239eea7dcabf19f144c77bf13d3674b5139aa51a99ba58118386c190af0e20bcbe020b05e1b7d0825953d92bf47897be08cd7751a37adb95d6a2e5224f55ab02013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b095e42001160014a82f02bc37bc5ed87d5f9fca02f8a6a7d89cdd5c000149ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80d293ad03012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac6600"); | |
32 | - } | |
33 | - | |
34 | - @Test | |
35 | - public void testSpendBIP32() { | |
36 | - SpendInput input = new SpendInput(btmAssetID, 11718900000L, "0014085a02ecdf934a56343aa59a3dec9d9feb86ee43"); | |
37 | - input.setSourceID("5ac79a73db78e5c9215b37cb752f0147d1157c542bb4884908ceb97abc33fe0a"); | |
38 | - input.setSourcePosition(0); | |
39 | - input.setRootPrivateKey("4864bae85cf38bfbb347684abdbc01e311a24f99e2c7fe94f3c071d9c83d8a5a349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257"); | |
40 | - input.setChange(true); | |
41 | - input.setKeyIndex(1); | |
42 | - input.setBipProtocol(BIPProtocol.BIP32); | |
43 | - input.setControlProgramIndex(447); | |
44 | - | |
45 | - Transaction tx = new Transaction.Builder() | |
46 | - .addInput(input) | |
47 | - .addOutput(new Output(btmAssetID, 1718900000L, "001409a0961e9b592a944ca3ded0ef9403fdb25b3793")) | |
48 | - .addOutput(new Output(btmAssetID, 9900000000L, "00145ade29df622cc68d0473aa1a20fb89690451c66e")) | |
49 | - .setTimeRange(0) | |
50 | - .build(); | |
51 | - | |
52 | - String rawTx = tx.rawTransaction(); | |
53 | - assert rawTx.equals("070100010160015e5ac79a73db78e5c9215b37cb752f0147d1157c542bb4884908ceb97abc33fe0affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0f280d42b0001160014085a02ecdf934a56343aa59a3dec9d9feb86ee43630240e37864ef905e943deb97e58b861c97f04f07c1d33b1ce4f1b6edddff0c8956a57d86fc922c45446cd38ea613fc3c9b7d5a2596f3dca7a7212f6da55b9515110420a29601468f08c57ca9c383d28736a9d5c7737cd483126d8db3d85490fe497b3502013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0aad1b3060116001409a0961e9b592a944ca3ded0ef9403fdb25b379300013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086d8f024011600145ade29df622cc68d0473aa1a20fb89690451c66e00"); | |
54 | - } | |
55 | - | |
56 | - //issue asset | |
57 | - @Test | |
58 | - public void testIssue() { | |
59 | - IssuanceInput issuanceInput = new IssuanceInput(); | |
60 | - issuanceInput.setAssetId("7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14"); | |
61 | - issuanceInput.setAmount(100000000000L); | |
62 | - issuanceInput.setProgram("ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad"); | |
63 | - issuanceInput.setNonce("ac9d5a527f5ab00a"); | |
64 | - issuanceInput.setKeyIndex(5); | |
65 | - issuanceInput.setRawAssetDefinition("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"); | |
66 | - issuanceInput.setRootPrivateKey("4864bae85cf38bfbb347684abdbc01e311a24f99e2c7fe94f3c071d9c83d8a5a349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257"); | |
67 | - | |
68 | - SpendInput spendInput = new SpendInput(btmAssetID, 9800000000L, "0014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e"); | |
69 | - spendInput.setBipProtocol(BIPProtocol.BIP32); | |
70 | - spendInput.setKeyIndex(1); | |
71 | - spendInput.setChange(true); | |
72 | - spendInput.setSourceID("4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea"); | |
73 | - spendInput.setSourcePosition(2); | |
74 | - spendInput.setControlProgramIndex(457); | |
75 | - spendInput.setRootPrivateKey("4864bae85cf38bfbb347684abdbc01e311a24f99e2c7fe94f3c071d9c83d8a5a349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257"); | |
76 | - | |
77 | - Transaction tx = new Transaction.Builder() | |
78 | - .addInput(issuanceInput) | |
79 | - .addInput(spendInput) | |
80 | - .addOutput(new Output("7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14", 100000000000L, "001437e1aec83a4e6587ca9609e4e5aa728db7007449")) | |
81 | - .addOutput(new Output(btmAssetID, 9700000000L, "00148be1104e04734e5edaba5eea2e85793896b77c56")) | |
82 | - .setTimeRange(0) | |
83 | - .build(); | |
84 | - | |
85 | - String rawTx = tx.rawTransaction(); | |
86 | - assert rawTx.equals("0701000201300008ac9d5a527f5ab00a7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad1480d0dbc3f402b001467b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d0125ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad01401ba3a3f2d3e9887e20da8d43666cc1602bb5421ffea9d2b4d7df9816fc174a43b25fb00db4775b10b679a8b5f8aa28555ebb8fb49f6275d43283daf8f5ac340d0160015e4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c480c1240201160014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e630240341c875fc815dc13ad811c9aa7c7af28a5c78765f77fd5a36dac263278fd605ae0553e34a1e645148370b7b397142ddbcd67ba33483279ab9894169b51e4f101201381d35e235813ad1e62f9a602c82abee90565639cc4573568206b55bcd2aed902013e7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad1480d0dbc3f4020116001437e1aec83a4e6587ca9609e4e5aa728db700744900013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8082a99124011600148be1104e04734e5edaba5eea2e85793896b77c5600"); | |
87 | - } | |
88 | - | |
89 | - | |
90 | - //retire asset | |
91 | - @Test | |
92 | - public void testRetire() { | |
93 | - String arbitrary = "77656c636f6d65efbc8ce6aca2e8bf8ee69da5e588b0e58e9fe5ad90e4b896e7958c"; | |
94 | - String assetId1 = "207265909236260b30942a6b00e30ceb769e0e58156b6482bac64117619c9dcf"; | |
95 | - | |
96 | - SpendInput input1 = new SpendInput(btmAssetID, 289100000L, "0014f1dc52048f439ac7fd74f8106a21da78f00de48f"); | |
97 | - input1.setRootPrivateKey(rootKey); | |
98 | - input1.setChange(true); | |
99 | - input1.setControlProgramIndex(41); | |
100 | - input1.setSourceID("0b2cff11d1d056d95237a5f2d06059e5395e86f60e69c1e8201ea624911c0c65"); | |
101 | - input1.setKeyIndex(1); | |
102 | - input1.setSourcePosition(0); | |
103 | - | |
104 | - SpendInput input2 = new SpendInput(assetId1, 70000000000L, "0014bb8a039726df1b649738e9973db14a4b4fd4becf"); | |
105 | - input2.setRootPrivateKey(rootKey); | |
106 | - input2.setChange(true); | |
107 | - input2.setControlProgramIndex(26); | |
108 | - input2.setSourceID("be0ac837e832c34a02968e54dab4f95cbeceb9fb01cd378310f6ea32219ee29b"); | |
109 | - input2.setKeyIndex(1); | |
110 | - input2.setSourcePosition(1); | |
111 | - | |
112 | - Output output1 = new Output(btmAssetID, 279100000L, "001414d362694eacfa110dc20dec77d610d22340f95b"); | |
113 | - Output output2 = Output.newRetireOutput(assetId1, 10000000000L, arbitrary); | |
114 | - Output output3 = new Output(assetId1, 60000000000L, "0014bb8a039726df1b649738e9973db14a4b4fd4becf"); | |
115 | - | |
116 | - Transaction transaction = new Transaction.Builder() | |
117 | - .addInput(input1) | |
118 | - .addInput(input2) | |
119 | - .addOutput(output1) | |
120 | - .addOutput(output2) | |
121 | - .addOutput(output3) | |
122 | - .setTimeRange(2000000) | |
123 | - .build(); | |
124 | - | |
125 | - String rawTransaction = transaction.rawTransaction(); | |
126 | - assert rawTransaction.equals("070180897a020160015e0b2cff11d1d056d95237a5f2d06059e5395e86f60e69c1e8201ea624911c0c65ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0a1ed89010001160014f1dc52048f439ac7fd74f8106a21da78f00de48f6302401660121218ab96d9f22cce712541ca34c53f4da40450669854341ca9624ad1cf10d1bfc96449fad5406224afd253ccfbdeab683f7ec7f9ee8f45e47a0c58500f2031ecc1bdd5fb9b40016358340b87646ea39faf55c0c105205cfdfdc6184725f40161015fbe0ac837e832c34a02968e54dab4f95cbeceb9fb01cd378310f6ea32219ee29b207265909236260b30942a6b00e30ceb769e0e58156b6482bac64117619c9dcf80f8cce284020101160014bb8a039726df1b649738e9973db14a4b4fd4becf630240d7b7f1c2ca1048fd6798234f2a1e895762f83e802507a008eff52605611b67390a74eaf228b76f5589ff109b2c20eaa65fad6de2e5ab8a25b54267b607df970b20a71547e1064b5edaad92cdce6b0ace832836ba28fdeaf0b83010bed247fe927c03013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0f48a85010116001414d362694eacfa110dc20dec77d610d22340f95b00014b207265909236260b30942a6b00e30ceb769e0e58156b6482bac64117619c9dcf80c8afa02501246a2277656c636f6d65efbc8ce6aca2e8bf8ee69da5e588b0e58e9fe5ad90e4b896e7958c00013e207265909236260b30942a6b00e30ceb769e0e58156b6482bac64117619c9dcf80b09dc2df0101160014bb8a039726df1b649738e9973db14a4b4fd4becf00"); | |
127 | - } | |
128 | -} |
@@ -0,0 +1,74 @@ | ||
1 | +package io.bytom.offline.api; | |
2 | + | |
3 | +import io.bytom.offline.util.AssetIdUtil; | |
4 | +import org.junit.Test; | |
5 | + | |
6 | +public class TransactionTest { | |
7 | + String btmAssetID = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; | |
8 | + | |
9 | + @Test | |
10 | + public void testIssuance() { | |
11 | + String rawAssetDefinition = "7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022676f6c64222c0a20202271756f72756d223a20312c0a20202272656973737565223a202266616c7365222c0a20202273796d626f6c223a2022474f4c44220a7d"; | |
12 | + String issuanceProgram = "0204bfcda069ae2000cf50143dac994b9cfc1a2c45a4332ecefbbb15824b9f1a537f0b49fd9f44b45151ad"; | |
13 | + System.out.println(AssetIdUtil.computeAssetID(rawAssetDefinition,issuanceProgram)); | |
14 | + IssuanceInput issuanceInput = new IssuanceInput("0541db69c21dc827092ddbc5673f5c1f0a09d3112da2a67c6644ec1be3fa38b3",2543541111111L,"0204bfcda069ae2000cf50143dac994b9cfc1a2c45a4332ecefbbb15824b9f1a537f0b49fd9f44b45151ad"); | |
15 | + issuanceInput.setVmVersion(1); | |
16 | + issuanceInput.setRootPrivateKey("b0cc39f8a4b9539fcc8f05c0df21563155767bfc6f2c4b801738eb831589d84afe549d3a89e8223762445a0f3bea5c192675636846f75f1455c6a23d30a37023"); | |
17 | + issuanceInput.setKeyIndex(3); | |
18 | + issuanceInput.setRawAssetDefinition("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022676f6c64222c0a20202271756f72756d223a20312c0a20202272656973737565223a202266616c7365222c0a20202273796d626f6c223a2022474f4c44220a7d"); | |
19 | + issuanceInput.setNonce(""); | |
20 | + | |
21 | + SpendInput spendInput = new SpendInput(); | |
22 | + spendInput.setAssetId(btmAssetID); | |
23 | + spendInput.setAmount(2853881270l); | |
24 | + spendInput.setSourceID("0b75ee155f60160ac14e038eaf7c67c820d77096a615ab00c1a3d9b52f9f246c"); | |
25 | + spendInput.setSourcePosition(0); | |
26 | + spendInput.setChange(false); | |
27 | + spendInput.setVmVersion(1); | |
28 | + spendInput.setProgram("0014e933e5a0545c63ff2c28eaedb47c831cac3b16cf"); | |
29 | + spendInput.setControlProgramIndex(2); | |
30 | + spendInput.setRootPrivateKey("b0cc39f8a4b9539fcc8f05c0df21563155767bfc6f2c4b801738eb831589d84afe549d3a89e8223762445a0f3bea5c192675636846f75f1455c6a23d30a37023"); | |
31 | + spendInput.setKeyIndex(1); | |
32 | + | |
33 | + OriginalOutput issuanceOutput = new OriginalOutput("0541db69c21dc827092ddbc5673f5c1f0a09d3112da2a67c6644ec1be3fa38b3",2543541111111L,"00145894d753c19d8fccce04db88f54751340ad8ca4f"); | |
34 | + OriginalOutput output = new OriginalOutput(btmAssetID,2753881270L,"0014b0b9455c1f77476b96858927d98e823d680ce889"); | |
35 | + | |
36 | + Transaction tx = new Transaction.Builder() | |
37 | + .addInput(issuanceInput) | |
38 | + .addInput(spendInput) | |
39 | + .addOutput(issuanceOutput) | |
40 | + .addOutput(output) | |
41 | + .setTimeRange(0) | |
42 | + .setSize(0) | |
43 | + .build(); | |
44 | + | |
45 | + String rawTransaction = tx.rawTransaction(); | |
46 | + System.out.println(rawTransaction); | |
47 | + } | |
48 | + | |
49 | + @Test | |
50 | + public void testSpendBIP44() { | |
51 | + SpendInput spendInput = new SpendInput(); | |
52 | + spendInput.setAssetId(btmAssetID); | |
53 | + spendInput.setAmount(2873881270l); | |
54 | + spendInput.setSourceID("6dd143552ff8fde887e65eb7c387ff77265d270dfc76d6488a0185476f66c601"); | |
55 | + spendInput.setSourcePosition(0); | |
56 | + spendInput.setChange(false); | |
57 | + spendInput.setVmVersion(1); | |
58 | + spendInput.setProgram("0014e933e5a0545c63ff2c28eaedb47c831cac3b16cf"); | |
59 | + spendInput.setControlProgramIndex(2); | |
60 | + spendInput.setRootPrivateKey("b0cc39f8a4b9539fcc8f05c0df21563155767bfc6f2c4b801738eb831589d84afe549d3a89e8223762445a0f3bea5c192675636846f75f1455c6a23d30a37023"); | |
61 | + spendInput.setKeyIndex(1); | |
62 | + | |
63 | + | |
64 | + OriginalOutput output = new OriginalOutput(btmAssetID,2773881270l,"0014b0b9455c1f77476b96858927d98e823d680ce889"); | |
65 | + Transaction tx = new Transaction.Builder() | |
66 | + .addInput(spendInput) | |
67 | + .addOutput(output) | |
68 | + .setTimeRange(0) | |
69 | + .setSize(0) | |
70 | + .build(); | |
71 | + System.out.println(tx.rawTransaction()); | |
72 | + System.out.println(tx.getTxID()); | |
73 | + } | |
74 | +} |
@@ -0,0 +1,147 @@ | ||
1 | +package io.bytom.offline.api; | |
2 | + | |
3 | +import com.amazonaws.util.StringUtils; | |
4 | +import com.google.crypto.tink.subtle.Hex; | |
5 | +import org.junit.Test; | |
6 | + | |
7 | +import java.io.IOException; | |
8 | + | |
9 | +import static org.junit.Assert.assertEquals; | |
10 | + | |
11 | +public class TxInputTest { | |
12 | + @Test | |
13 | + public void testSpendInput() throws IOException { | |
14 | + SpendInput input = new SpendInput(); | |
15 | + input.setAssetId("fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a"); | |
16 | + input.setAmount(254354); | |
17 | + input.setSourceID("fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409"); | |
18 | + input.setSourcePosition(3); | |
19 | + input.setVmVersion(1); | |
20 | + input.setProgram(Hex.encode("spendProgram".getBytes())); | |
21 | + input.appendStateData(Hex.encode("stateData".getBytes())); | |
22 | + input.appendWitnessComponent(Hex.encode("arguments1".getBytes())); | |
23 | + input.appendWitnessComponent(Hex.encode("arguments2".getBytes())); | |
24 | + | |
25 | + byte[] serializeInputCommitment = input.serializeInput(); | |
26 | + String wantStr= StringUtils.join("", | |
27 | + "01", // asset version | |
28 | + "5f", // input commitment length | |
29 | + "01", // spend type flag | |
30 | + "5d", // spend commitment length | |
31 | + "fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409", // source id | |
32 | + "fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a", // assetID | |
33 | + "92c30f", // amount | |
34 | + "03", // source position | |
35 | + "01", // vm version | |
36 | + "0c", // spend program length | |
37 | + "7370656e6450726f6772616d", // spend program | |
38 | + "0109", // state length | |
39 | + "737461746544617461", // state | |
40 | + "17", // witness length | |
41 | + "02", // argument array length | |
42 | + "0a", // first argument length | |
43 | + "617267756d656e747331", // first argument data | |
44 | + "0a", // second argument length | |
45 | + "617267756d656e747332" // second argument data | |
46 | + ); | |
47 | + | |
48 | + assertEquals(wantStr,Hex.encode(serializeInputCommitment)); | |
49 | + } | |
50 | + | |
51 | + @Test | |
52 | + public void testIssuanceInput() throws IOException { | |
53 | + IssuanceInput issuanceInput = new IssuanceInput(); | |
54 | + issuanceInput.setAmount(254354L); | |
55 | + issuanceInput.setVmVersion(1); | |
56 | + issuanceInput.setProgram(Hex.encode("issuanceProgram".getBytes())); | |
57 | + issuanceInput.setNonce(Hex.encode("nonce".getBytes())); | |
58 | + issuanceInput.setRawAssetDefinition(Hex.encode("assetDefinition".getBytes())); | |
59 | + issuanceInput.appendWitnessComponent(Hex.encode("arguments1".getBytes())); | |
60 | + issuanceInput.appendWitnessComponent(Hex.encode("arguments2".getBytes())); | |
61 | + | |
62 | + byte[] serializeInputCommitment = issuanceInput.serializeInput(); | |
63 | + String wantStr= StringUtils.join("", | |
64 | + "01", // asset version | |
65 | + "2a", // serialization length | |
66 | + "00", // issuance type flag | |
67 | + "05", // nonce length | |
68 | + "6e6f6e6365", // nonce | |
69 | + "a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf", // assetID | |
70 | + "92c30f", // amount | |
71 | + "38", // input witness length | |
72 | + "0f", // asset definition length | |
73 | + "6173736574446566696e6974696f6e", // asset definition | |
74 | + "01", // vm version | |
75 | + "0f", // issuanceProgram length | |
76 | + "69737375616e636550726f6772616d", // issuance program | |
77 | + "02", // argument array length | |
78 | + "0a", // first argument length | |
79 | + "617267756d656e747331", // first argument data | |
80 | + "0a", // second argument length | |
81 | + "617267756d656e747332" // second argument data | |
82 | + ); | |
83 | + | |
84 | + assertEquals(wantStr,Hex.encode(serializeInputCommitment)); | |
85 | + } | |
86 | + | |
87 | + @Test | |
88 | + public void testVetoInput() throws IOException { | |
89 | + VetoInput vetoInput = new VetoInput(); | |
90 | + vetoInput.setSourceID("fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409"); | |
91 | + vetoInput.setAssetId("fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a"); | |
92 | + vetoInput.setSourcePosition(3); | |
93 | + vetoInput.setAmount(254354L); | |
94 | + vetoInput.setVmVersion(1); | |
95 | + vetoInput.setProgram(Hex.encode("spendProgram".getBytes())); | |
96 | + vetoInput.setVote("af594006a40837d9f028daabb6d589df0b9138daefad5683e5233c2646279217294a8d532e60863bcf196625a35fb8ceeffa3c09610eb92dcfb655a947f13269".getBytes()); | |
97 | + vetoInput.appendWitnessComponent(Hex.encode("arguments1".getBytes())); | |
98 | + vetoInput.appendWitnessComponent(Hex.encode("arguments2".getBytes())); | |
99 | + | |
100 | + | |
101 | + byte[] serializeInputCommitment = vetoInput.serializeInput(); | |
102 | + | |
103 | + String wantStr= StringUtils.join("", | |
104 | + "01", // asset version | |
105 | + "d701", // input commitment length | |
106 | + "03", // veto type flag | |
107 | + "53", // veto commitment length | |
108 | + "fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409", // source id | |
109 | + "fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a", // assetID | |
110 | + "92c30f", // amount | |
111 | + "03", // source position | |
112 | + "01", // vm version | |
113 | + "0c", // veto program length | |
114 | + "7370656e6450726f6772616d", // veto program | |
115 | + "00", // state length | |
116 | + "8001", //xpub length | |
117 | + "6166353934303036613430383337643966303238646161626236643538396466306239313338646165666164353638336535323333633236343632373932313732393461386435333265363038363362636631393636323561333566623863656566666133633039363130656239326463666236353561393437663133323639", //voter xpub | |
118 | + "17", // witness length | |
119 | + "02", // argument array length | |
120 | + "0a", // first argument length | |
121 | + "617267756d656e747331", // first argument data | |
122 | + "0a", // second argument length | |
123 | + "617267756d656e747332" // second argument data | |
124 | + ); | |
125 | + | |
126 | + assertEquals(wantStr,Hex.encode(serializeInputCommitment)); | |
127 | + } | |
128 | + | |
129 | + @Test | |
130 | + public void testCoinbaseInput() throws IOException { | |
131 | + CoinbaseInput coinbaseInput = new CoinbaseInput(); | |
132 | + coinbaseInput.setArbitrary(Hex.encode("arbitrary".getBytes())); | |
133 | + | |
134 | + byte[] serializeInputCommitment = coinbaseInput.serializeInput(); | |
135 | + | |
136 | + String wantStr= StringUtils.join("", | |
137 | + "01", // asset version | |
138 | + "0b", // input commitment length | |
139 | + "02", // coinbase type flag | |
140 | + "09", // arbitrary length | |
141 | + "617262697472617279", // arbitrary data | |
142 | + "00" // witness length | |
143 | + ); | |
144 | + | |
145 | + assertEquals(wantStr,Hex.encode(serializeInputCommitment)); | |
146 | + } | |
147 | +} |
@@ -0,0 +1,58 @@ | ||
1 | +package io.bytom.offline.api; | |
2 | + | |
3 | +import com.amazonaws.util.StringUtils; | |
4 | +import com.google.crypto.tink.subtle.Hex; | |
5 | +import org.junit.Test; | |
6 | + | |
7 | +import java.io.IOException; | |
8 | + | |
9 | +import static org.junit.Assert.assertEquals; | |
10 | + | |
11 | +public class TxOutputTest { | |
12 | + String assetID = "81756fdab39a17163b0ce582ee4ee256fb4d1e156c692b997d608a42ecb38d47"; | |
13 | + @Test | |
14 | + public void SerializationOriginalTxOutputTest() throws IOException { | |
15 | + OriginalOutput output = new OriginalOutput(assetID,254354L,Hex.encode("TestSerializationTxOutput".getBytes())); | |
16 | + output.appendStateData(Hex.encode("stateData".getBytes())); | |
17 | + | |
18 | + byte[] serializeOutputCommitment = output.serializeOutput(); | |
19 | + String wantStr= StringUtils.join("", | |
20 | + "01", // asset version | |
21 | + "00", // output type | |
22 | + "49", // serialization length | |
23 | + "81756fdab39a17163b0ce582ee4ee256fb4d1e156c692b997d608a42ecb38d47", // assetID | |
24 | + "92c30f", // amount | |
25 | + "01", // version | |
26 | + "19", // control program length | |
27 | + "5465737453657269616c697a6174696f6e54784f7574707574", // control program | |
28 | + "0109", // state data length | |
29 | + "737461746544617461", // state data | |
30 | + "00" // witness length | |
31 | + ); | |
32 | + | |
33 | + assertEquals(wantStr,Hex.encode(serializeOutputCommitment)); | |
34 | + } | |
35 | + | |
36 | + @Test | |
37 | + public void SerializationVetoOutputTest() throws IOException { | |
38 | + OriginalOutput output = new OriginalOutput(assetID,254354L,Hex.encode("TestSerializationTxOutput".getBytes())); | |
39 | + output.appendStateData(Hex.encode("stateData".getBytes())); | |
40 | + | |
41 | + byte[] serializeOutputCommitment = output.serializeOutput(); | |
42 | + String wantStr= StringUtils.join("", | |
43 | + "01", // asset version | |
44 | + "00", // output type | |
45 | + "49", // serialization length | |
46 | + "81756fdab39a17163b0ce582ee4ee256fb4d1e156c692b997d608a42ecb38d47", // assetID | |
47 | + "92c30f", // amount | |
48 | + "01", // version | |
49 | + "19", // control program length | |
50 | + "5465737453657269616c697a6174696f6e54784f7574707574", // control program | |
51 | + "0109", // state data length | |
52 | + "737461746544617461", // state data | |
53 | + "00" // witness length | |
54 | + ); | |
55 | + | |
56 | + assertEquals(wantStr,Hex.encode(serializeOutputCommitment)); | |
57 | + } | |
58 | +} |